SFINAE does not apply :(
-
Folgendes ist (wie zu erwarten war) Unsinn: (EDIT: Wie sich weiter unten herausstellt: ist doch kein Unsinn)
template <typename T, typename Stub = mplex::char_<0> > struct takes_one { typedef char yes[1]; typedef char no[2]; template <typename C> static yes& test(typename C::template apply <Stub>*); template <typename> static no& test(...); static const bool value = sizeof(test<T>(nullptr)) == sizeof(yes); }; int main () { std::cout << takes_one <is_equal>::value; }
Ist klar was ich versuche zu erreichen? (rausfinden wie viele Parameter apply akzeptiert ohne das hinterlegen zu müssen in is_equal).
Ich habe die Vermutung dass das unmöglich ist, aber aus Hoffnung frage ich hier trotzdem.EDIT: erweiterbar auf unendliche viele Parameter wäre von da aus ja easy (mit variadics ohne limit)
-
hmm, die Frage ist für mich nicht so ganz einfach zu verstehen.
Aber ich denke, apply ist ein Member Functiontemplate von is_equal?d.h. irgendwie so?:
#include <iostream> struct is_equal { template <typename T> void apply(T) {} }; struct is_equal2 { template <typename T> void apply(T, T) {} }; template <typename C, typename R, typename... P> constexpr unsigned cnt(R (C::*p)(P...)) { return sizeof...(P); } template <typename T, typename Stub = char* > struct takes_one { static const bool value = cnt(& T::template apply<Stub>) == 1; }; int main () { std::cout << takes_one<is_equal>::value << "\n"; std::cout << takes_one<is_equal2>::value << "\n"; }
-
Oh ja ups. So einfach ist es leider nicht.
Beispiel:
struct is_equal { constexpr static const int arity = 2; // <- will ich mir sparen template <typename T, typename U> struct apply { using type = typename std::is_same <T, U>::type; }; }; struct is_space { constexpr static const int arity = 1; // <- will ich mir sparen template <typename CharT> struct apply { using type = bool_ <CharT::value == ' ' || CharT::value == '\n'; //...more }; };
ideal application
takes_one<is_space>::value // true takes_one<is_equal>::value // false takes_two<is_equal>::value // true takes_two<is_space>::value // false
further expansion of principle
takes<2, is_equal>::value // true
Aber wenn das unmöglich ist mache ich es vermutlich so:
template <unsigned Arity> struct functor { constexpr static const unsigned arity = Arity; // more stuff }; struct is_equal : functor <2> { //... };
-
Dann verstehe ich allerdings nicht mehr, warum Deine Lösung ganz oben "Unsinn" sein soll
Wenn ich die ausprobiere, dann funktioniert eigentlich alles.
siehe http://coliru.stacked-crooked.com/a/074d432531546335
-
g++ 4.9.2: error does not take 1 argument
g++ 5.1.0: compiles
clang 3.6.0: compilesMuss wohl noch auf mingw-w64 warten und bis dahin clang verwenden (ich will g++ und clang unterstützen (aber immer nur die neuste Version))
EDIT: jupp, sieht jetzt so aus:
std::cout << has_arity_v <is_equal, 1>::value << "\n"; // 0 std::cout << has_arity_v <is_equal, 2>::value << "\n"; // 1 std::cout << has_arity_v <is_space, 1>::value << "\n"; // 1 std::cout << has_arity_v <is_space, 2>::value << "\n"; // 0