【问题标题】:Why specialization based on enable_if is not picked up by compiler为什么编译器没有选择基于 enable_if 的专业化
【发布时间】:2015-06-04 23:03:17
【问题描述】:

我想专门针对某些类型的类,例如基于 std::is_arithmetic 的类。尽管编译器没有“看到”我基于“enable_if”的专业化并选择了原理/主模板。你能帮我解决这个... 下面是用g++ 4.8编译后的sn-p代码和输出

#include < iostream >  
#include < type_traits >  
#include < string >  

template < typename T1, typename T2 = void >  
struct TestT  
{  
    static const bool is_int = false;  
    static const bool is_str = false;  
};

template < typename T>  
struct TestT < T,  
       std::enable_if< std::is_arithmetic<t>::value, T >::type >  
{  
    static const bool is_int = true;  
    static const bool is_str = false;  
};  

template < typename T>
struct TestT < std::string, T >  
{  
    static const bool is_int = false;  
    static const bool is_str = true;  
};  

class enum TestE  
{  
    Last  
};

int main(int argc, char* argv[])  
{
    std::cout << "Enum is_int: " << TestT<TestE>::is_int  
              << ", is_str: " << TestT<TestE>::is_str << std::endl;  
    std::cout << "string is_int: " << TestT<std::string>::is_int  
              << ", is_str: " << TestT<std::string>::is_str << std::endl;  
    std::cout << "int is_int: " << TestT<int>::is_int  
              << ", is_str: " << TestT<int>::is_str << std::endl;  
    return 0;
}  

上面的输出是:

Enum is_int: 0, is_str: 0 // 预期
string is_int: 0, is_str: 1 // 预期
int is_int: 0, is_str: 0 // 未预期

非常感谢您的帮助,并提前感谢您

【问题讨论】:

  • 请发布一些可以编译的代码

标签: c++ c++11 template-specialization enable-if


【解决方案1】:

您需要将第二个参数(由::type 别名的类型)保留为未指定或void,以便它与主模板的默认参数匹配:

struct TestT<T,  
       std::enable_if<std::is_arithmetic<T>::value>::type> 

您还需要在std::enable_if 语句之前使用typename,或者使用std::enable_if_t(并省略::type):

struct TestT<T, std::enable_if_t<std::is_arithmetic<T>::value>>

第二个专业也是如此:

template<>
struct TestT<std::string>  
{  
    static const bool is_int = false;  
    static const bool is_str = true;  
};

最后,在此专业化中,is_int 应设置为 true

template<typename T>  
struct TestT<T, std::enable_if_t<std::is_arithmetic<T>::value>>  
{  
    static const bool is_int = true;  
    static const bool is_str = false;  
};

Live Demo

更好的版本可能是保留一个特化并使用std::is_same 来测试int 和一个类型特征来测试字符串:

template<class T>struct is_string:std::false_type{};
template<>struct is_string<std::string>:std::true_type{};
template<std::size_t N>struct is_string<char const(&)[N]>:std::true_type{};
template<>struct is_string<char const*>:std::true_type{};
template<>struct is_string<char const*const>:std::true_type{};
template<>struct is_string<char const*volatile>:std::true_type{};
// on and on...

template<typename T>  
struct TestT  
{  
    static const bool is_int = std::is_same<T, int>();  
    static const bool is_str = is_string<T>();  
};

【讨论】:

  • 我点击了检查链接,但您能否解释一下为什么第二个参数必须与主模板匹配。如果要查看第二个专业化,对于 std::string,第二个参数不匹配,但它适用于字符串
  • @Yurishd 这是我的疏忽,std::string 的特化应该有 void 或特化中的第二个空参数。它起作用的原因是因为模板比主模板更专业(第一个参数接受std::string,第二个参数接受任何内容)。因此被选中。正确的代码应该是:coliru.stacked-crooked.com/a/c1675935d0719125
猜你喜欢
  • 1970-01-01
  • 2021-10-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-07
  • 1970-01-01
相关资源
最近更新 更多