1.何为sfine
Substitiution Faliure is Not an Error
.这项规则被应用于函数模板重载决议时。当替换模板具体参数或演绎参数失败时,该具现化被从当前重载集中抛弃而不是让编译器报错。这个特性也被应用于模板元编程中。
2.参数替换发生时间
模板参数(
template parameters
)被模板变量(template arguments
)代替两次:
explicitly specified template arguments are substituted before template argument deduction
deduced arguments and the arguments obtained from the defaults are substituted after template argument deduction
什么地方会发生变量替换呢
All type used in function type
all types used in the template parameter declarations
all expressions used in the function type
all expressions used in a template parameter declaration
all expressions used in the explicit specifier
sfine何时发生
A substitution failure is any situation when the type or expression above would be ill-formed (with a required diagnostic), if written using the substituted arguments.
Only the failures in the types and expressions in the immediate context of the function type or its template parameter types or its explicit specifier (since C++20) are SFINAE errors. If the evaluation of a substituted type/expression causes a side-effect such as instantiation of some template specialization, generation of an implicitly-defined member function, etc, errors in those side-effects are treated as hard errors. A lambda expression is not considered part of the immediate context. (since C++20)
ttemplate <typename A>
struct B { using type = typename A::type; };
template <
class T,
class = typename T::type, // SFINAE failure if T has no member type
class U = typename B<T>::type // hard error if T has no member type
// (guaranteed to not occur as of C++14)
> void foo (int);
3.Type SFINAE
type sfinae都有哪些
- attempting to instantiate a pack expansion containing multiple packs of different lengths
- attempting to create an array of void, array of reference, array of function, array of negative size, array of non-integral size, or array of size zero.
template <int I> void div(char(*)[I % 2 == 0] = 0) {
// this overload is selected when I is even
}
template <int I> void div(char(*)[I % 2 == 1] = 0) {
// this overload is selected when I is odd
}
- attempting to use a type that is not a class or enumeration on the left of a scope resolution operator ::
template <class T> int f(typename T::B*);
template <class T> int f(T);
int i = f<int>(0); // uses second overload
- attempting to use a member of a type, where
- the type does not contain the specified member
- the specified member is not a type where a type is required
- the specified member is not a template where a template is required
- the specified member is not a non-type where a non-type is required
template <int I> struct X { };
template <template <class T> class> struct Z { };
template <class T> void f(typename T::Y*){}
template <class T> void g(X<T::N>*){}
template <class T> void h(Z<T::template TT>*){}
struct A {};
struct B { int Y; };
struct C { typedef int N; };
struct D { typedef int TT; };
struct B1 { typedef int Y; };
struct C1 { static const int N = 0; };
struct D1 {
template <typename T>
struct TT
{
};
};
int main() {
// Deduction fails in each of these cases:
f<A>(0); // A does not contain a member Y
f<B>(0); // The Y member of B is not a type
g<C>(0); // The N member of C is not a non-type
h<D>(0); // The TT member of D is not a template
// Deduction succeeds in each of these cases:
f<B1>(0);
g<C1>(0);
h<D1>(0);
}
// todo: needs to demonstrate overload resolution, not just failure
- attempting to create a pointer to reference
- attempting to create a reference to void.
- attempting to create pointer to member of T, where T is not a class type
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);
};
- attempting to give an invalid type to a non-type template parameter
template <class T, T> struct S {};
template <class T> int f(S<T, T()>*);
struct X {};
int i0 = f<X>(0);
// todo: needs to demonstrate overload resolution, not just failure
- attempting to perform an invalid conversion in
- in a template argument expression
- in an expression used in function declaration
template <class T, T*> int f(int);
int i2 = f<int,1>(0); // can’t conv 1 to int*
// todo: needs to demonstrate overload resolution, not just failure
- attempting to create a function type with a parameter of type void
- attempting to create a function type which returns an array type or a function type
- attempting to create a cv-qualified function type(until C++11)