为什么 SFINAE 需要"启用"类模板参数?
Why SFINAE requires the 'Enable' class template parameter?
(此问题与c++ 11/c++ 14无关:示例使用c++ 03编译)
enable_bool<T>
只有在T
= bool
时才有成员::type
template <class T>
struct enable_bool
{};
template <>
struct enable_bool< bool >
{ typedef bool type; };
在下一个代码片段中,部分专门化是正确的(参见gcc.godbolt.org)
template <class T, class U, class Enable = T>
struct Foo
{
static int bar() { return 0; }
};
template <class T, class U>
struct Foo< T, U, typename enable_bool<T>::type >
{
static int bar() { return 1; }
};
int main()
{
return Foo <int, bool>::bar();
}
由于enable_bool<T>::type
已经对应T
(当T
为bool
时)
我们很想分解参数T
和Enable
。
但是编译器抱怨(见gcc.godbolt.org)
template <class T, class U>
struct Foo
{
static int bar() { return 0; }
};
template <class T, class U> //ERROR non-deducible template parameter 'T'
struct Foo< typename enable_bool<T>::type, U >
{
static int bar() { return 1; }
};
为什么编译器不能在上面的部分特化中推导出模板参数T
?
最后这个问题甚至与SFINAE无关!
考虑这个没有SFINAE的非常简单的代码片段:
无论T
的类型如何,enable<T>::type
总是与T
相同。
template <class T>
struct enable
{ typedef T type; }; // Enable always
template <class U, class V>
struct Foo
{
static int bar() { return 0; }
};
template <class X, class Y> //ERROR non-deducible parameter 'X'
struct Foo< typename enable<X>::type, Y >
{
static int bar() { return 1; }
};
int main()
{
return Foo<int, bool>::bar();
}
当编译器尝试将Foo<int, bool>
与Foo<typename enable<X>::type,Y>
匹配时
-
1st param U = int <--> enable<X>::type
=>无法推断X
-
2nd param V = bool <--> Y
编译器不能从方程int = enable<X>::type
推导出X
。
因此,编译器需要开发人员的帮助。
需要另一个参数:Enable
.
下面的固定代码段添加了Enable
类模板参数。编译器执行以下匹配:
-
1st param U =int <--> X
-
2nd param V =bool<--> Y
-
3rd param Enable=int <--> enable<X>::type
(从第1参数推导出X
)
(第三个参数是int
,因为声明class Enable=U
默认表示第三个参数与第一个相同)
固定的片段:
template <class T>
struct enable
{ typedef T type; }; // Enable always
template <class U, class V, class Enable = U>
struct Foo
{
static int bar() { return 0; }
};
template <class X, class Y> // Compiler can deduce 'X'
struct Foo< X, Y, typename enable<X>::type >
{
static int bar() { return 1; }
};
int main()
{
return Foo<int, bool>::bar();
}
相关文章:
- 视觉工作室 2017;启用 /permissive 时,类型 "const wchar_t *" 的参数与类型 "PWSTR" 的参数不兼容
- 如何启用转换模板参数 T 以常量 T?
- SFINAE 和模板函数实例化:为什么在启用了 SFINAE 类型的函数参数中使用模板参数时无法推断模板参数?
- 如果作为参数传递的函子不带参数,则启用模板
- 如何使用布尔参数为按位运算符启用C++警告
- 如果每个参数都可以转换为特定类型,则启用 ctor
- 根据模板参数的默认值启用模板参数类型的自动扣除
- 如何在模板参数为bidirectional_iterator时启用模板类专用化
- 如何使用布尔模板参数启用成员函数?
- 如何仅在给定n个以上参数的情况下启用可变模板构造函数_if
- 不存在的标识符在非启用函数模板中用作默认参数
- 仅当参数可将某个类型的符号解释时,如何启用函数
- 'auto ... arg'的参数包形式在 lambda 中启用,但在函数中未启用?
- C++模板添加/启用基于模板参数的构造函数
- 根据模板参数启用模板 Ctor
- 启用从此可变参数模板共享
- 如何启用具有可变模板参数的类(_I)
- 只有模板参数有成员功能时,才启用成员功能
- 为什么 SFINAE 需要"启用"类模板参数?
- 如何在MSVC中为传递给变分函数的非POD参数启用警告/错误