【问题标题】:How does enable_if help select specializations of a class template?enable_if 如何帮助选择类模板的特化?
【发布时间】:2020-09-16 09:23:44
【问题描述】:

我对 SFINAE 有基本的了解,并且我想我了解很多关于 std::enable_if 如何利用它来选择函数模板专业化的示例,但我很难理解它在课堂上的工作原理模板。

以下示例来自cppreference.com's explanation of std::enable_if

template<class T, class Enable = void>
class A {}; // primary template

template<class T>
class A<T, typename std::enable_if<std::is_floating_point<T>::value>::type> {
}; // specialization for floating point types

我无法理解以这种方式使用std::enable_if 如何帮助选择专业。 (我不怀疑它确实如此。)

当编译器看到像A&lt;float&gt; specialized; 这样的声明时,它会看到两个可能的模板实例化:

  1. “主模板”A&lt;T, Enable&gt; 其中Tfloat 类型,Enable 是void 类型(因为默认值)。
  2. 特化A&lt;T, void&gt;,其中Tfloat 类型,voidenable_if 表达式的结果。

那些不是模棱两可的吗?两者都有效地导致A&lt;T, void&gt;,那么为什么选择专业化?

在另一种情况下,例如A&lt;int&gt; primary;,编译器的选项似乎是:

  1. 主要A&lt;T, Enable&gt;,其中Tint 类型,Enablevoid 类型。
  2. 专业化A&lt;T, ?&gt;,其中Tint 类型,? 代表我完全迷失的地方。在这种情况下,enable_if 条件为假,因此它没有定义 type,这会留下A&lt;int, typename &gt;。这不是语法错误吗?即使面对 SFINAE?

【问题讨论】:

    标签: c++ template-meta-programming template-specialization enable-if class-template


    【解决方案1】:

    来自partial specialization 的类模板参考:

    当一个类或变量(C++14 起)模板被实例化,并且有部分特化可用时,编译器必须决定是使用主模板还是它的部分特化之一。

    如果只有一个特化与模板参数匹配,则使用该特化

    在这种情况下,如果特化的第二个参数格式正确,则选择它,正是因为它是特化,而不是主模板。

    如果第二个模板参数不是格式正确,那么SFINAE 会起作用。特别是:

    当用显式指定或推导的类型替换模板参数失败时,特化将从重载集中丢弃而不是导致编译错误

    以下类型错误是 SFINAE 错误:

    试图使用一个类型的成员,其中 该类型不包含指定的成员

    这是如何完成的,即编译器如何准确地丢弃特化,而不是给出错误,没有指定;编译器只需要做正确的事情。

    【讨论】:

      【解决方案2】:

      那些不是模棱两可的吗?两者都有效地导致A&lt;T, void&gt;,那么为什么选择专业化?

      不,特化比主模板更特化,因为它要求第二个参数是void(假设enable_if 条件为真),而主模板不需要'限制它。

      专业化A&lt;T, ?&gt;,其中Tint 类型,? 代表我完全迷失的地方。在这种情况下,enable_if 条件为假,因此它没有定义类型,这给您留下了A&lt;int, typename &gt;。这不是语法错误吗?即使面对 SFINAE?

      没错,特化中的第二个参数被证明是无效的。但这是一个“软”错误,它会被 SFINAE 检测到并使编译器放弃特化。 (我不认为编译器会在文本上用空字符串替换enable_if_t&lt;...&gt;::type,然后分析A&lt;int, typename &gt;;它更有可能会在注意到enable_if 中缺少::type 时立即丢弃专业化。)

      【讨论】:

      • 你的最后一句话,括号里的那句话,是我克服心理障碍的关键。谢谢!
      猜你喜欢
      • 1970-01-01
      • 2012-08-13
      • 2021-08-26
      • 1970-01-01
      • 1970-01-01
      • 2012-04-05
      • 1970-01-01
      • 2019-08-30
      • 1970-01-01
      相关资源
      最近更新 更多