C SFINAE 例子?

新手上路,请多包涵

我想进入更多的模板元编程。我知道 SFINAE 代表“替代失败不是错误”。但是有人可以告诉我 SFINAE 的好用处吗?

原文由 rlbond 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 575
2 个回答

这是一个例子( 来自这里):

 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 的成员指针”。相反,它只使用 ... 形式返回两个,因此计算结果为 false,int 不是类类型。

原文由 Greg Rogers 发布,翻译遵循 CC BY-SA 3.0 许可协议

在我看来,其他答案提供的示例比需要的更复杂。

这是 cppreference 中稍微容易理解的示例:

 #include <iostream>

// this overload is always in the set of overloads
// ellipsis parameter has the lowest ranking for overload resolution
void test(...)
{
    std::cout << "Catch-all overload called\n";
}

// this overload is added to the set of overloads if
// C is a reference-to-class type and F is a pointer to member function of C
template <class C, class F>
auto test(C c, F f) -> decltype((void)(c.*f)(), void())
{
    std::cout << "Reference overload called\n";
}

// this overload is added to the set of overloads if
// C is a pointer-to-class type and F is a pointer to member function of C
template <class C, class F>
auto test(C c, F f) -> decltype((void)((c->*f)()), void())
{
    std::cout << "Pointer overload called\n";
}

struct X { void f() {} };

int main(){
  X x;
  test( x, &X::f);
  test(&x, &X::f);
  test(42, 1337);
}

输出:

 Reference overload called
Pointer overload called
Catch-all overload called

如您所见,在第三次测试调用中,替换失败且没有错误。

原文由 user6547518 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题