Substitution failure is not an error (SFINAE) refers to a situation in C++ where an invalid substitution of template parameters is not in itself an error. David Vandevoorde first introduced the acronym SFINAE to describe related programming techniques.
So the simple answer is YES.
" typename " is a keyword in the C++ programming language used when writing templates. It is used for specifying that a dependent name in a template definition or declaration is a type.
Expression SFINAE is explained quite well in the paper you linked, I think. It's SFINAE on expressions. If the expression inside decltype
isn't valid, well, kick the function from the VIP lounge of overloads. You can find the normative wording at the end of this answer.
A note on VC++: They didn't implement it completely. On simple expressions, it might work, but on others, it won't. See a discussion in the comments on this answer for examples that fail. To make it simple, this won't 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);
}
With Clang, this outputs the expected:
Could call with reference
Could call with pointer
Couldn't 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 isn't quite up to 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'
A common use of Expression SFINAE is when defining traits, like a trait to check if a class sports a certain 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)) {};
Live example. (Which, surprisingly, works again on GCC 4.7.1.)
See also this answer of mine, which uses the same technique in another environment (aka without traits).
Normative wording:
§14.8.2 [temp.deduct]
p6 At certain points in the template argument deduction process it is necessary to take a function type that makes use of template parameters and replace those template parameters with the corresponding template arguments. This is done at the beginning of template argument deduction when any explicitly specified template arguments are substituted into the function type, and again at the end of template argument deduction when any template arguments that were deduced or obtained from default arguments are substituted.
p7 The substitution occurs in all types and expressions that are used in the function type and in template parameter declarations. The expressions include not only constant expressions such as those that appear in array bounds or as nontype template arguments but also general expressions (i.e., non-constant expressions) inside
sizeof
,decltype
, and other contexts that allow non-constant expressions.p8 If a substitution results in an invalid type or expression, type deduction fails. An invalid type or expression is one that would be ill-formed if written using the substituted arguments. [...]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With