C ++ SFINAE的例子?

我想进入更多的模板元编程。 我知道SFINAE代表“替代失败不是一个错误”。 但有人可以让我看到SFINAE的良好用途吗?


下面是一个例子(从这里):

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 };
};

IsClassT<int>::Yes ,0不能转换为int int::*因为int不是一个类,所以它不能有成员指针。 如果SFINAE不存在,那么你会得到一个编译器错误,像'0不能转换为非类类型int的成员指针'。 相反,它只是使用返回Two的...形式,因此计算结果为false,int不是类类型。


我喜欢使用SFINAE来检查布尔条件。

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 */
}

它可能非常有用。 例如,我用它来检查使用运算符逗号收集的初始化程序列表是否不大于固定大小

template<int N>
struct Vector {
    template<int M> 
    Vector(MyInitList<M> const& i, char(*)[M <= N] = 0) { /* ... */ }
}

该列表仅在M小于N时被接受,这意味着初始化程序列表中没有太多元素。

语法char(*)[C]表示:指向元素类型为char和大小为C的数组的指针。 如果C为false(这里为0),那么我们得到无效类型char(*)[0] ,指向一个零大小的数组:SFINAE使得模板将被忽略。

boost::enable_if表示,看起来像这样

template<int N>
struct Vector {
    template<int M> 
    Vector(MyInitList<M> const& i, 
           typename enable_if_c<(M <= N)>::type* = 0) { /* ... */ }
}

在实践中,我经常发现能够检查条件的有用能力。


Boost的enable_if库为使用SFINAE提供了一个不错的界面。 Boost.Iterator库是我最喜欢的用法示例之一。 SFINAE用于启用迭代器类型转换。

链接地址: http://www.djcxy.com/p/72901.html

上一篇: C++ SFINAE examples?

下一篇: Creating a new object from dynamic type info