http://en.wikipedia.org/wiki/Substitution_failure_is_not_an_error
#include <iostream>
template <typename T>
struct has_typedef_foobar {
// Types "yes" and "no" are guaranteed to have different sizes,
// specifically sizeof(yes) == 1 and sizeof(no) == 2.
typedef char yes[1];
typedef char no[2];
template <typename C>
static yes& test(typename C::foobar*);
template <typename>
static no& test(...);
// If the "sizeof" the result of calling test<T>(0) would be equal to the sizeof(yes),
// the first overload worked and T has a nested type named foobar.
static const bool value = sizeof(test<T>(0)) == sizeof(yes);
};
struct foo {
typedef float foobar;
};
int main() {
std::cout << std::boolalpha;
std::cout << has_typedef_foobar<int>::value << std::endl;
std::cout << has_typedef_foobar<foo>::value << std::endl;
}
Above example shows SFAINE .
1) sizeof(char) is defined to be equal to 1. Since yes is a typedef for an array of one char, its size has to be one. Likewise, since no is a typedef for an array of two chars, its size must be 2 * sizeof(char), which is 2.
2) The function test is never called, so the definition is unnecessary - the sizeof operator is a compile-time operation, so the compiler just looks at the size of the return type of the instantiation of test with the specified template parameter. Because it's not called, a definition is unnecessary, similar to making private non-defined copy constructor in order to make a class non copy-constructable.
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