【问题标题】:Template specialisation with default argument [duplicate]具有默认参数的模板特化[重复]
【发布时间】:2018-12-30 22:03:04
【问题描述】:

我有一个程序如下。有一个基本模板 struct X 和 SFINAE 的部分专业化。

template <typename T, typename U = void>
struct X{
  X() {
    std::cout << "in 1" << std::endl;
  };
};

template <typename T>
struct X< T, std::enable_if_t<std::is_integral_v<T>> > {
  X() {
    std::cout << "in 2" << std::endl;
  };
};

int main() {
  X<int> x;
}

运行程序时会打印in 2

  1. 为什么选择第二个特化而不是第一个,因为它们都有效地声明了struct X&lt;int, void&gt;。是什么让std::enable_if_t&lt;std::is_integral_v&lt;T&gt;&gt; 比基本模板中显示的默认模板类型参数更专业?

  2. 为什么基本模板的默认类型参数必须与要调用的部分特化和要打印的in 2 的部分特化定义的类型相同。 为什么更改为std::enable_if_t&lt;std::is_integral_v&lt;T&gt;, bool&gt; 会导致基础模板in 1 被调用?

【问题讨论】:

  • 你不需要std::enable_if_t 来问这个问题。只需在第一种情况下将部分特化定义为template &lt;typename T&gt; struct X&lt;T, void&gt;,在第二种情况下使用bool 而不是void

标签: c++ templates c++14 sfinae partial-specialization


【解决方案1】:

您的问题的答案在于 Template Partial Ordering。这是编译器用来确定哪个模板最适合的机制(无论是函数模板重载,还是在您的情况下,类模板特化)。

简而言之,您的通用模板实现有两个参数TU,而您的SFINAE 专业化只有T 参数,而第二个是从T 推导出来的。因此,它比一般情况更专业,最后,当您引用 X&lt;int, void&gt; 时,会选择专业化。

现在问题 2。假设我们将 enable_if 参数替换为 bool 而不是 void。现在我们的专业化将是X&lt;int, bool&gt;,而不是X&lt;int, void&gt;,所以当您引用X&lt;int&gt;,即X&lt;int, void&gt;时,它不再与专业化匹配,因为它们是两种不同的类型。

【讨论】:

    【解决方案2】:

    1) [...] 是什么让 std::enable_if_t> 比基本模板中显示的默认模板类型参数更专业?

    那么你知道吗,如果两个模板匹配,则选择更专业的。

    嗯...第二个更专业,因为如果X 匹配专业化(所以如果X 是一个整数类型),它也匹配通用版本。

    但存在几种类型(例如:std::stringvoid),它们与通用版本匹配,但与专业化版本不匹配。

    所以专业化比通用版本更专业,所以当两个模板匹配时是首选。

    为什么基模板的默认类型参数必须与部分特化定义的类型相同才能调用部分特化并在 2 中打印。为什么改成std::enable_if_t, bool>会导致1中的基础模板被调用?

    您必须了解默认类型值的技巧。

    你有那个通用版本

    template <typename T, typename U = void>
    struct X;
    

    所以写X&lt;int&gt; x,你写X&lt;int, void&gt; x;,肯定匹配通用版本。

    专业是

    template <typename T>
    struct X< T, std::enable_if_t<std::is_integral_v<T>>>;
    

    问题:X&lt;int, void&gt; 匹配 X&lt; T, std::enable_if_t&lt;std::is_integral_v&lt;T&gt;&gt;&gt; 吗?

    答案:是的,因为int 是整数,所以std::enable_if_t&lt;std::is_integral_v&lt;T&gt;&gt;void 代替。

    现在假设泛型特化变成了

    template <typename T>
    struct X< T, std::enable_if_t<std::is_integral_v<T>, bool>>
    

    我们知道X&lt;int&gt; x 又是X&lt;int, void&gt; x 并且再次匹配通用版本。

    问题:X&lt;int, void&gt; 也匹配 X&lt; T, std::enable_if_t&lt;std::is_integral_v&lt;T&gt;, bool&gt;&gt;

    答案:不,因为std::enable_if_t&lt;std::is_integral_v&lt;T&gt;, bool&gt; 变成boolX&lt;int, void&gt; 不匹配X&lt;int, bool&gt;

    所以通用版本是唯一匹配并被选中的版本。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-20
      • 2013-09-13
      • 1970-01-01
      • 1970-01-01
      • 2021-12-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多