The SFINAE expression is explained quite well in the document you linked, I think. This is SFINAE in expressions. If the expression inside decltype invalid, ok, remove the function from the VIP congestion room. You can find the normative wording at the end of this answer.
Note on VC ++: they did not fully implement it. On simple expressions, this may work, but on others it will not. See the discussion in the comments in this answer for examples that fail. To make it simple, this will not work:
#include <iostream> // catch-all case void test(...) { std::cout << "Couldn't call\n"; } // catch when C is a reference-to-class type and F is a member function pointer template<class C, class F> auto test(C c, F f) -> decltype((c.*f)(), void()) // 'C' is reference type { std::cout << "Could call on reference\n"; } // catch when C is a pointer-to-class type and F is a member function pointer template<class C, class F> auto test(C c, F f) -> decltype((c->*f)(), void()) // 'C' is pointer type { std::cout << "Could call on pointer\n"; } struct X{ void f(){} }; int main(){ X x; test(x, &X::f); test(&x, &X::f); test(42, 1337); }
Clang returns the expected value:
You can call with a link I can call with a pointer
Failed to call
With MSVC, I get ... well, a compiler error:
1> src \ main.cpp (20): error C2995: '' unknown-type 'test (C, F)': function template has already been defined
1> src \ main.cpp (11): see declaration of 'test'
It also seems that GCC 4.7.1 does not quite match the task:
source.cpp: In substitution of 'template decltype ((c. * f (), void ())) test (C, F) [with C = X *; F = void (X :: *) ()] ':
source.cpp: 29: 17: required from here
source.cpp: 11: 6: error: cannot apply member pointer 'f' to 'c', which is of non-class type 'X *'
source.cpp: In substitution of 'template decltype ((c. * f (), void ())) test (C, F) [with C = int; F = int] ':
source.cpp: 30: 16: required from here
source.cpp: 11: 6: error: 'f' cannot be used as a member pointer, since it is of type 'int'
The common use of the SFINAE expression is to define traits as a sign to check if a class supports a particular member function:
struct has_member_begin_test{ template<class U> static auto test(U* p) -> decltype(p->begin(), std::true_type()); template<class> static auto test(...) -> std::false_type; }; template<class T> struct has_member_begin : decltype(has_member_begin_test::test<T>(0)) {};
Real-time example. (surprisingly, works again on GCC 4.7.1.)
See also this my answer , which uses the same technique in a different environment (aka without signs).
Normative wording:
Β§14.8.2 [temp.deduct]
p6 At certain points in the process of subtracting a template argument, it is necessary to take the type of function that uses the template parameters and replace these template parameters with the corresponding template arguments. This is done at the beginning of the output of the template argument, when any explicitly specified template arguments are substituted into the function type, and again at the end of the output of the template argument, when any template arguments that were derived or obtained from the default arguments are substituted .
p7 Substitution occurs in all types and expressions that are used in a function type and in template parameter declarations. Expressions include not only constant expressions , such as those that appear within the boundaries of an array or as arguments to a nontype pattern , but also general expressions (i.e. decltype expressions) inside sizeof , decltype and other contexts that allow non-constant expressions.
p8 If substitution results in an invalid type or expression, the deduction type fails. An invalid type or expression is one that would be poorly formed if it were written using substituted arguments. [...]