C++ SFINAE examples?
I want to get into more template meta-programming. I know that SFINAE stands for "substitution failure is not an error." But can someone show me a good use for SFINAE?
Heres one example (from here):
template<typename T>
class IsClassT {
private:
typedef char One;
typedef struct { char a[2]; } Two;
template<typename C> static One test(int C::*);
// Will be chosen if T is anything except a class.
template<typename C> static Two test(...);
public:
enum { Yes = sizeof(IsClassT<T>::test<T>(0)) == 1 };
enum { No = !Yes };
};
When IsClassT<int>::Yes
is evaluated, 0 cannot be converted to int int::*
because int is not a class, so it can't have a member pointer. If SFINAE didn't exist, then you would get a compiler error, something like '0 cannot be converted to member pointer for non-class type int'. Instead, it just uses the ...
form which returns Two, and thus evaluates to false, int is not a class type.
I like using SFINAE
to check boolean conditions.
template<int I> void div(char(*)[I % 2 == 0] = 0) {
/* this is taken when I is even */
}
template<int I> void div(char(*)[I % 2 == 1] = 0) {
/* this is taken when I is odd */
}
It can be quite useful. For example, i used it to check whether an initializer list collected using operator comma is no longer than a fixed size
template<int N>
struct Vector {
template<int M>
Vector(MyInitList<M> const& i, char(*)[M <= N] = 0) { /* ... */ }
}
The list is only accepted when M is smaller than N, which means that the initializer list has not too many elements.
The syntax char(*)[C]
means: Pointer to an array with element type char and size C
. If C
is false (0 here), then we get the invalid type char(*)[0]
, pointer to a zero sized array: SFINAE makes it so that the template will be ignored then.
Expressed with boost::enable_if
, that looks like this
template<int N>
struct Vector {
template<int M>
Vector(MyInitList<M> const& i,
typename enable_if_c<(M <= N)>::type* = 0) { /* ... */ }
}
In practice, i often find the ability to check conditions a useful ability.
Boost's enable_if library offers a nice clean interface for using SFINAE. One of my favorite usage examples is in the Boost.Iterator library. SFINAE is used to enable iterator type conversions.
链接地址: http://www.djcxy.com/p/72902.html上一篇: 头文件中的C ++代码
下一篇: C ++ SFINAE的例子?