What is SFINAE’s usage?
Before we get to SFINAE, let’s look at a piece of code, and it all starts with this piece of code.
template <typename T>
void show(typename T::iterator x, typename T::iterator y) {
for (; x != y; ++x) cout << *x << endl;
}
int main() {
show<int>(16, 18);
}
When you compile the above code, you will find that it fails to compile and you will get the following error.
sfinae.cc:13:21: error: no matching function for call to ‘show(int, int)’
show<int>(16, 18);
^
sfinae.cc:6:6: note: candidate: template<class T> void show(typename T::iterator, typename T::iterator)
void show(typename T::iterator x, typename T::iterator y)
^
sfinae.cc:6:6: note: template argument deduction/substitution failed:
sfinae.cc: In substitution of ‘template<class T> void show(typename T::iterator, typename T::iterator) [with T = int]’:
.................
To be clear, this error means that your template parameter type cannot be found; the template parameter is required to be a class type, and has an iterator class internal type. And then int doesn’t satisfy this requirement. No matching declaration was found so the following error was reported. It is easy to fix this error by adding an overload to the template as follows:
template <typename T>
void show(T a, T b) {
cout << a << "; " << b << endl;
}
At this point the above code can run normally. This Is the so-called SFINAE solution, full name Is “Substitution Failure Is Not An Error,” this Is a feature of the compiler, for example when the compiler tries to according to the show (16, 18) code>,
T to find: : iterator code>, this type of template matching found themselves unable to replace, it cause the compiler to sell the wrong then abruptly, but the compiler chose to ignore this Error and continue to find, Throw an error if you can't find anything by the end of all searches. This is called the SFINAE method. So the question is, what are the USES of SFINAE?", listen to the following analysis.
An example of SFINAE
SFINAE can be used to determine whether a type has an Iterator during compilation, as follows:
template <typename T>
struct has_iterator {
template <typename U>
static char test(typename U::iterator* x);
template <typename U>
static long test(U* x);
static const bool value = sizeof(test<T>(0)) == 1;
};
In the above code, there are two test function templates, when the first one is matched, the char type is returned, so the size is 1, the value is true, when the second one is matched, the value is long, so the size is definitely not 1, and the value is false. This is a neat way to determine at compile time whether a type supports Iterator or not. Here is the test code:
int main() {
has_iterator<vector<int> > test;
if( test.value )
cout << "vector have iterator" << endl;
else
cout << "vector not have iterator";
has_iterator<int> test2;
if( test2.value )
cout << "int have iterator" << endl;
else
cout << "int not have iterator" << endl;
}
SFINAE in Boost/Standard library
SFINAE features are heavily used in boost and standard libraries, typically such as STD ::enable_if
, STD ::is_class
, STD ::void_t
, etc. A large number of type traits
are also heavily used in C++11
. The following is the specific implementation of is_class
:
template<typename T>
class is_class {
typedef char yes[1];
typedef char no [2];
template<typename C> static yes& test(int C::*); // selected if C is a class type
template<typename C> static no& test(...); // selected otherwise
public:
static bool const value = sizeof(test<T>(0)) == sizeof(yes);
};
If it's a class, it matches the function that returns yes, and then value is true. This example is basically the same as the example above.
Read More:
- C language string processing error warning, c4996, sprintf, predicted, c4996, strcpy, c4996, strcat
- C++:error C2228: left of ‘.str’ must have class/struct/union
- Differences between length() size() and C strlen() of C + + string member functions
- C / C + + rounding function ceil(), floor ()
- error C2057: expected constant expression (Can the size of an array in C language be defined when the program is running?)
- Error c2137 of C language: empty character constant (Fixed)
- Solve the problem of error: cannot pass objects of non trivially copyable type ‘STD:: String’ in C / C + +
- ninja Compiling the C compiler identification source file CMakeCCompilerId.c failed
- [Solved] Dev-C++ [Error] ‘for‘ loop initial declarations are only allowed in C99 or C11 mode
- [Solved] Linux C++ Compile Error: c++: internal compiler error: Killed (program cc1plus)
- Error c2065: ‘new’: undeclared identifier, mainly because it is a. C file
- Solution to the flash of running result of dev C / C + +
- C / C + + library function (tower / tower) realizes the conversion of letter case
- Chinese garbled code when vscode calls CMD to run C / C + +
- Fatal error C1853 error occurs when there are mixed .c files in the VS project
- To solve the running error of eclipse for C / C + +: launch failed binary not found
- Error: unrecognized command line option “-std=c++11”, to solve the problem that ubuntu does not support c++11
- Solution to the problem of no C / C + + option in the new project of eclipse
- MPI cannot be found in C / C + +
- C / C + + error handling (document): unhandled exception: 0xc0000005: access violation while reading location 0x00000000