Mihooke的技术专栏 C++ and Python Coder

C++ SFINAE

2018-07-29

阅读:

C++

SFINAE(Substitution Failure Is Not An Error )即匹配失败不是一个错误,这种技术是用在模板中,可用于判断类的某个属性是否存在,可把错误提前到编译期,这涉及到重载函数的匹配策略,具体看下面的代码分析。

template<typename T>
struct has_no_destroy
{
  template <typename C> static char test(decltype(&C::no_destroy));
  template <typename C> static int32_t test(...);
  const static bool value = sizeof(test<T>(0)) == 1;
};

这段代码摘自muduo库的Singleton.h文件。 这里定义了一个has_no_destroy的struct,用于判断类中是否有no_destroy的属性;struct中声明了两个test重载函数,一个参数是decltype(&C::no_destroy),我们假设no_destory是typename C的成员变量,decltype是C++11关键字,用于推测表达式的类型,由于有&取地址符号,所以这里参数类型是一个指针,返回值是char类型;另一个参数是…,表示可以是任意的参数,也就是说无论test函数传递什么参数都会在这里得到匹配,它的返回值是4字节的int类型;最后还定义了一个bool值,注意看sizeof(test(0)),调用了test(0),首先编译器会查找T中是否有no_destroy属性,如果有,这个第一个test函数是最佳匹配;如果T中没有no_destroy属性,此时,如果没有声明第二个test重载函数,编译器会报出编译错误,否则第二个test会被匹配到,所以这句话的意思就是如果C中有no_destroy,value的值就是true,如果没有no_destroy,value就是false,因此我们可以这样使用上面的技术:

    if (!detail::has_no_destroy<T>::value)
    {
      ……
    }

Comments

Content