enable_if 如何帮助 select 专业化 class 模板?
How does enable_if help select specializations of a class template?
我对 SFINAE 有基本的了解,我想我理解许多 std::enable_if
如何利用它来 select 函数模板特化的例子,但我很难总结我想知道它如何用于 class 模板。
以下例子来自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
如何帮助 select 专业化。 (我不怀疑它确实如此。)
当编译器看到像 A<float> specialized;
这样的声明时,它会看到两个可能的模板实例化:
- "primary template"
A<T, Enable>
其中 T
是类型 float
并且 Enable 是类型 void
(因为默认值)。
- 特化
A<T, void>
,其中 T
是类型 float
,void
是 enable_if
.[=60= 表达式的结果]
那些不是很暧昧吗?两者都有效地导致 A<T, void>
,那么为什么选择专业化?
在另一种情况下,例如 A<int> primary;
,编译器的选项似乎是:
- 主要
A<T, Enable>
,其中 T
是类型 int
,Enable
是类型 void
。
- 专业化
A<T, ?>
,其中 T
是类型 int
,?
代表我完全迷失的地方。在本例中,enable_if
条件为假,因此它没有定义 type
,这使您得到 A<int, typename >
。那不是语法错误吗?即使面对SFINAE?
Aren't those ambiguous? Both effectively result in A<T, void>
, so why is the specialization chosen?
不,特化比主模板更特化,因为它要求第二个参数为void
(假设enable_if
条件为true),而主模板不限制它。
The specialization, A<T, ?>
, where T
is the type int
and the ?
represents where I'm completely lost. In this case, the enable_if
condition is false, so it doesn't define type, which leaves you with A<int, typename >
. Isn't that a syntax error? Even in the face of SFINAE?
确切地说,专业化中的第二个参数无效。但这是一个 "soft" 错误,由 SFINAE 检测到并使编译器放弃特化。 (我不认为编译器会在文本上用空字符串替换 enable_if_t<...>::type
然后分析 A<int, typename >
;更有可能的是它会在注意到缺少 ::type
时立即丢弃特化enable_if
.)
来自 class 个模板的 partial specialization 上的参考:
When a class or variable (since C++14) template is instantiated, and there are partial specializations available, the compiler has to decide if the primary template is going to be used or one of its partial specializations.
If only one specialization matches the template arguments, that specialization is used
在这种情况下,如果专业化的第二个参数格式正确,则选择它,正是因为它是专业化,而不是主模板。
如果第二个模板参数不是格式正确的,则SFINAE开始。特别是:
When substituting the explicitly specified or deduced type for the template parameter fails, the specialization is discarded from the overload set instead of causing a compile error.
和
The following type errors are SFINAE errors:
attempting to use a member of a type, where
the type does not contain the specified member
如何做到这一点,即编译器究竟如何丢弃特化,而不是给出错误,没有具体说明;编译器只需要做正确的事情。
我对 SFINAE 有基本的了解,我想我理解许多 std::enable_if
如何利用它来 select 函数模板特化的例子,但我很难总结我想知道它如何用于 class 模板。
以下例子来自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
如何帮助 select 专业化。 (我不怀疑它确实如此。)
当编译器看到像 A<float> specialized;
这样的声明时,它会看到两个可能的模板实例化:
- "primary template"
A<T, Enable>
其中T
是类型float
并且 Enable 是类型void
(因为默认值)。 - 特化
A<T, void>
,其中T
是类型float
,void
是enable_if
.[=60= 表达式的结果]
那些不是很暧昧吗?两者都有效地导致 A<T, void>
,那么为什么选择专业化?
在另一种情况下,例如 A<int> primary;
,编译器的选项似乎是:
- 主要
A<T, Enable>
,其中T
是类型int
,Enable
是类型void
。 - 专业化
A<T, ?>
,其中T
是类型int
,?
代表我完全迷失的地方。在本例中,enable_if
条件为假,因此它没有定义type
,这使您得到A<int, typename >
。那不是语法错误吗?即使面对SFINAE?
Aren't those ambiguous? Both effectively result in
A<T, void>
, so why is the specialization chosen?
不,特化比主模板更特化,因为它要求第二个参数为void
(假设enable_if
条件为true),而主模板不限制它。
The specialization,
A<T, ?>
, whereT
is the typeint
and the?
represents where I'm completely lost. In this case, theenable_if
condition is false, so it doesn't define type, which leaves you withA<int, typename >
. Isn't that a syntax error? Even in the face of SFINAE?
确切地说,专业化中的第二个参数无效。但这是一个 "soft" 错误,由 SFINAE 检测到并使编译器放弃特化。 (我不认为编译器会在文本上用空字符串替换 enable_if_t<...>::type
然后分析 A<int, typename >
;更有可能的是它会在注意到缺少 ::type
时立即丢弃特化enable_if
.)
来自 class 个模板的 partial specialization 上的参考:
When a class or variable (since C++14) template is instantiated, and there are partial specializations available, the compiler has to decide if the primary template is going to be used or one of its partial specializations.
If only one specialization matches the template arguments, that specialization is used
在这种情况下,如果专业化的第二个参数格式正确,则选择它,正是因为它是专业化,而不是主模板。
如果第二个模板参数不是格式正确的,则SFINAE开始。特别是:
When substituting the explicitly specified or deduced type for the template parameter fails, the specialization is discarded from the overload set instead of causing a compile error.
和
The following type errors are SFINAE errors:
attempting to use a member of a type, where the type does not contain the specified member
如何做到这一点,即编译器究竟如何丢弃特化,而不是给出错误,没有具体说明;编译器只需要做正确的事情。