【问题标题】:Template specialization with enable_if带有 enable_if 的模板特化
【发布时间】:2019-04-12 08:45:22
【问题描述】:

我正在尝试创建一个采用类型名的模板函数。我想将这个模板专门用于一些基本类型,如int、long、string 和double。对于所有其他类型,我需要有一个专门的类/结构代码,以及其他类型的默认代码。

我当前的代码是这个:

// Declaration
template <typename T, typename enable_if<is_class<T>::value>::type = 0>
void test(T& value);

template <typename T, typename enable_if<!is_class<T>::value>::type = 0>
void test(T& value);

template <> // What am i supposed to write here ?
void test<int>(int& value);

// Definition
template <typename T, typename enable_if<is_class<T>::value>::type = 0>
void test(T& value) {
    cout << "Class/struct test" << endl;
}

template <typename T, typename enable_if<!is_class<T>::value>::type = 0>
void test(T& value) {
    cout << "Other types test" << endl;
}

template <>
void test<int>(int& value) {
    cout << "int test" << endl;
}

此代码无法编译。我不知道我应该在int 专用模板中写什么。

我正在尝试使用the examples from this documentation,但无法使用。

【问题讨论】:

  • 当is_class&lt;T&gt;::value 为真时,enable_if&lt;is_class&lt;T&gt;::value&gt;::type 为void。您尝试将0 分配给void。
  • 您是否阅读了您发布的链接中的注释?它几乎从字面上描述了你的错误。
  • 最好使用重载函数来实现此目的,因为您不能部分特化函数模板。

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


【解决方案1】:

typename enable_if&lt;is_class&lt;T&gt;::value&gt;::type = 0 没有意义,因为typename enable_if&lt;is_class&lt;T&gt;::value&gt;::type 将引用void;您可以将其更改为typename enable_if&lt;is_class&lt;T&gt;::value&gt;::type* = nullptr。那么对于int的完整特化,注意test有两个模板参数,那么

// Declaration
template <typename T, typename enable_if<is_class<T>::value>::type* = nullptr>
void test(T& value);

template <typename T, typename enable_if<!is_class<T>::value>::type* = nullptr>
void test(T& value);

template <>
void test<int, nullptr>(int& value);

// Definition
template <typename T, typename enable_if<is_class<T>::value>::type*>
void test(T& value) {
    cout << "Class/struct test" << endl;
}

template <typename T, typename enable_if<!is_class<T>::value>::type*>
void test(T& value) {
    cout << "Other types test" << endl;
}

template <>
void test<int, nullptr>(int& value) {
    cout << "int test" << endl;
}

LIVE

或者简单地将typename enable_if&lt;is_class&lt;T&gt;::value&gt;::type 作为返回类型。例如

// Declaration
template <typename T>
typename enable_if<is_class<T>::value>::type test(T& value);

template <typename T>
typename enable_if<!is_class<T>::value>::type test(T& value);

template <>
void test<int>(int& value);

// Definition
template <typename T>
typename enable_if<is_class<T>::value>::type test(T& value) {
    cout << "Class/struct test" << endl;
}

template <typename T>
typename enable_if<!is_class<T>::value>::type test(T& value) {
    cout << "Other types test" << endl;
}

template <>
void test<int>(int& value) {
    cout << "int test" << endl;
}

LIVE

【讨论】:

  • 有趣的是它不能为 Visual Studio Error C2912 explicit specialization 'void test&lt;int,nullptr&gt;(int &amp;)' is not a specialization of a function template 编译
  • @StackDanny Emm... 似乎第二个版本适用于 MSVS。 rextester.com/QTLR35350
  • @songyuanyao 是的,我刚在你编辑的时候尝试过。工作正常。不过还是很奇怪,也有人讨论过here
  • void test&lt;int&gt;(int &amp;) 版本也可以用 MSVS 编译。
【解决方案2】:

您需要在函数参数中使用 std::enable_if 而不是模板参数:

// Declaration
template <typename T>
void test(T& value, enable_if_t<is_class<T>::value>* = nullptr);

template <typename T>
void test(T& value, enable_if_t<!is_class<T>::value>* = nullptr);

template <>
void test<int>(int& value, enable_if_t<!is_class<int>::value>*);

// Definition
template <typename T>
void test(T& value, enable_if_t<is_class<T>::value>*){
    cout << "Class/struct test" << endl;
}

template <typename T>
void test(T& value, enable_if_t<!is_class<T>::value>*) {
    cout << "Other types test" << endl;
}

template <>
void test<int>(int& value, enable_if_t<!is_class<int>::value>*) {
    cout << "int test" << endl;
}

【讨论】:

  • 如果处理得当,把它作为模板参数是完全可以的。这会污染函数签名,而且 IMO 也更难阅读。
  • 是的,同意。模板参数更好
猜你喜欢
  • 1970-01-01
  • 2020-09-01
  • 2012-08-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-05
  • 1970-01-01
相关资源
最近更新 更多