Content deleted Content added
mNo edit summary |
No edit summary |
||
(48 intermediate revisions by 40 users not shown) | |||
Line 1:
{{Short description|C++ programming technique}}
'''Substitution failure is not an error''' ('''SFINAE''') refers to a situation in [[C++]] where an invalid substitution of [[template (programming)|template]] parameters is not in itself an error. David Vandevoorde first introduced the acronym SFINAE to describe related programming techniques.<ref>{{cite book | last=Vandevoorde | first=David | coauthors=Nicolai M. Josuttis | title=C++ Templates: The Complete Guide | publisher=Addison-Wesley Professional | year=2002 | isbn=0-201-73484-2}}</ref>▼
{{Use dmy dates|date=December 2023}}
▲'''Substitution failure is not an error''' ('''SFINAE''')
Specifically, when creating a candidate set for [[overload resolution]], some (or all) candidates of that set may be the result of
==Example==
The following example illustrates a basic instance of SFINAE:
<
struct Test {
};
template <typename T>
void f(typename T::
template <typename T>
void f(T) {}
int main() {
// thanks to SFINAE.
return 0;
}
</syntaxhighlight>
Here, attempting to use a non-class type in a qualified name (<code>T::
Although SFINAE was initially introduced to avoid creating ill-formed programs when unrelated template declarations were visible (e.g., through the inclusion of a header file), many developers later found the behavior useful for compile-time introspection. Specifically, it allows a template to determine certain properties of its template arguments at instantiation time.
For example, SFINAE can be used to determine if a type contains a certain typedef:
<
#include <iostream>
template <typename T>
struct
// foobar.
};
struct
};
int main() {
return 0;
}
</syntaxhighlight>
When <code>T</code> has the nested type <code>
== C++11 simplification ==
Developers of [[Boost C++ Libraries|Boost]] used SFINAE to great effect in boost::enable_if<ref name="enable_if">[http://www.boost.org/doc/libs/release/libs/utility/enable_if.html Boost Enable If]</ref> and in other ways.▼
In [[C++11]], the above code could be simplified to:
<syntaxhighlight lang="cpp">
#include <iostream>
#include <type_traits>
template <typename T, typename = void>
struct HasTypedefFoobar : std::false_type {};
template <typename T>
struct HasTypedefFoobar<T, std::void_t<typename T::foobar>> : std::true_type {};
struct Foo {
using foobar = float;
};
int main() {
std::cout << std::boolalpha;
std::cout << HasTypedefFoobar<int>::value << std::endl;
std::cout << HasTypedefFoobar<Foo>::value << std::endl;
return 0;
}
</syntaxhighlight>
With the standardisation of the detection idiom in the [http://en.cppreference.com/w/cpp/experimental/lib_extensions_2 Library fundamental v2 (n4562)] proposal, the above code could be re-written as follows:
<syntaxhighlight lang="cpp">
#include <iostream>
#include <type_traits>
template <typename T>
using HasTypedefFoobarUnderlying = typename T::foobar;
struct Foo {
using foobar = float;
};
int main() {
std::cout << std::boolalpha;
std::cout << std::is_detected<HasTypedefFoobarUnderlying, int>::value << std::endl;
std::cout << std::is_detected<HasTypedefFoobarUnderlying, Foo>::value << std::endl;
return 0;
}
</syntaxhighlight>
▲
==References==
{{reflist}}
{{C++ programming language}}
[[Category:C++]]
[[Category:Articles with example C++ code]]
[[Category:Software design patterns]]
|