A few questions for C ++ 11 experts.
I'm fighting SFINAE and I came across a strange case where g ++ (4.9.2) and clang ++ (3.5.0) behave differently.
I prepared the following code example. Sorry, but I can not make it much more concise.
#include <string> #include <iostream> #include <typeinfo> #include <type_traits> template <typename X> class foo { private: template <typename R> using enableIfIsInt = typename std::enable_if<std::is_same<X, int>::value, R>::type; public: foo () { } template <typename R = void> enableIfIsInt<R> bar () { std::cout << "bar: is int\n"; } void bar () { std::cout << "bar: isn't int; is [" << typeid(X).name() << "]{" << typeid(enableIfIsInt<void>).name() << "}\n"; } }; int main () { foo<long> fl; foo<int> fi; fl.bar(); fi.bar(); return 0; }
My idea was to create a foo<X> template that (via SFINAE) could define a method in one way or another, depending on the argument of X template.
The program compiles well with g ++ 4.9.2, but clang ++ 3.5.0 gives the following error
test.cpp:13:36: error: no type named 'type' in 'std::__1::enable_if<false, void>'; 'enable_if' cannot be used to disable this declaration = typename std::enable_if<std::is_same<X, int>::value, R>::type; ^~~~~~~~~~~~~~~~~~~~~~~~~~~ test.cpp:26:23: note: in instantiation of template type alias 'enableIfIsInt' requested here << typeid(enableIfIsInt<void>).name() << "}\n"; ^ test.cpp:36:7: note: in instantiation of member function 'foo<long>::bar' requested here fl.bar(); ^ 1 error generated.
I suppose this is the correct clang ++, but my first question is for C ++ 11 experts: who is right? g ++ or clang ++?
About the release of a program released by g ++, follows
bar: isn't int; is [i]{v}
therefore g ++ seems to ignore the fl.bar(); statement fl.bar(); .
Now a small change: I am changing the second version of foo<X>::bar() this way
void bar () { std::cout << "bar: isn't int; is [" << typeid(X).name() << "]\n"; }
removing std::enable_if inside the abomination function. Now both g ++ and clang ++ compile without problems, and the output for both compiled versions of the program is
bar: isn't int; is [l] bar: isn't int; is [i]
So my second question is: what am I doing wrong? Why in case of int I do not get the version of "is int" foo<X>::bar() ?
Be patient with me if I do stupid things: I'm trying to learn C ++ 11.
And sorry for my bad english.