我对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;
它将看到两个可能的模板实例,以满足。
A<T, Enable>
哪儿 T
是类型 float
而Enable是类型 void
因为默认值)。A<T, void>
哪儿 T
是类型 float
和 void
的表达式的结果。enable_if
.这些不是模棱两可吗? 两者实际上都会导致 A<T, void>
,为什么要选择专业化呢?
在不同的情况下,比如 A<int> primary;
,编译器的选项似乎是。
A<T, Enable>
,其中 T
是类型 int
和 Enable
是类型 void
.A<T, ?>
,其中 T
是类型 int
和 ?
代表着我完全迷失的地方。 在这种情况下 enable_if
条件为假,所以它没有定义 type
,这让你有 A<int, typename >
. 这不是语法错误吗? 即使面对SFINAE也是如此?从参考文献中可以看到 部分专业化 的类模板。
当一个类或变量(自C++14以来)模板被实例化时,如果存在部分特化,编译器必须决定是使用主模板还是其部分特化之一。
如果只有一个特化符合模板参数,则使用该特化。
在这种情况下,如果特殊化的第2个论点形式良好,则选择它。正因为 它是一个特殊化,而不是主模板。
如果第2个模板参数是 不 匀称 SFINAE 踢到了。特别是:当将明确指定或推导的类型替换为模板参数失败时,会从重载集中抛弃特殊化。
当用显式指定的或推导的类型代替模板参数失败时,特殊化将从重载集中被丢弃。而不是造成编译错误.
和
以下类型错误是SFINAE错误。
试图使用一个类型的成员,而该类型不包含指定的成员。
如何做到这一点,即编译器到底如何抛弃这个特殊化,而不是给出一个错误,没有规定,只要求编译器做正确的事情。
这些不是模棱两可吗?两者的结果实际上都是
A<T, void>
,那为什么要选择这个专业呢?
不,专业是 更专业 比主模板要好,因为它要求第二个参数是 void
(假设 enable_if
条件为真),而主模板并没有限制它。
的特殊化。
A<T, ?>
,其中T
是类型int
和?
代表着我完全迷失的地方。在这种情况下enable_if
条件为false,所以它没有定义类型,这样你就有了A<int, typename >
. 这不是语法错误吗?即使面对SFINAE?
没错,特殊化中的第二个参数原来是无效的。但这是一个 "软 "错误,SFINAE会检测到这个错误,并使编译器放弃这个特殊化。(我不认为编译器会用文本替换掉那些 "软 "错误。enable_if_t<...>::type
用一个空字符串,然后分析 A<int, typename >
它更有可能的是,一旦它发现缺少这种专门化,它就会放弃这种专门化。::type
在 enable_if
.)