enable_if如何帮助选择类模板的专业化?

How does enable_if help select specializations of a class template?

本文关键字:选择 专业化 帮助 if 何帮助 enable      更新时间:2023-10-16

我对SFINAE有基本的了解,我想我了解std::enable_if如何利用它来选择函数模板专用化的许多示例,但是我很难理解它如何用于类模板。

以下示例来自 cppreference.com 对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<float> specialized;的声明时,它将看到两个可能的模板实例化:

  1. "主模板"A<T, Enable>其中Tfloat类型,启用是void类型(因为默认值(。
  2. 特化A<T, void>其中Tfloat类型,void是带有enable_if的表达式的结果。

这些不是模棱两可吗? 两者都有效地导致A<T, void>,那么为什么选择专业化呢?

在另一种情况下,如A<int> primary;,编译器的选项似乎是:

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

来自关于类模板部分专用化的参考:

当类或变量(自 C++14 以来(模板实例化,并且存在部分专用化可用时,编译器必须决定是使用主模板还是其部分专用化之一。

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

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

如果第二个模板参数的格式不正确,则 SFINAE 将启动。特别:

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

以下类型错误是 SFINAE 错误:

尝试使用某个类型的成员,其中 类型不包含指定的成员

如何做到这一点,即编译器如何准确地放弃专业化,而不是给出错误,没有指定;编译器只需要做正确的事情。

这些不是模棱两可吗?两者都有效地导致A<T, void>,那么为什么选择专业化呢?

否,专用化比主模板更专用,因为它要求void第二个参数(假设enable_if条件为 true(,而主模板不限制它。

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

没错,专业化中的第二个参数被证明是无效的。但这是一个"软"错误,SFINAE 检测到它并使编译器放弃专用化。(我不认为编译器会用空字符串文本替换enable_if_t<...>::type然后分析A<int, typename >;更有可能的是,一旦它注意到enable_if缺乏::type,它就会放弃专业化。