(这个问题与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; }
};
为什么编译器不能在上面的部分特化中推导出模板参数?
最佳答案 最后这个问题甚至与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>
>第一个参数U = int< – >启用< X> :: type =>不能推断X.
>第二个参数V = bool< – > ÿ
编译器不是为了从等式int = enable< X> :: type中推导出X.
因此,编译器需要开发人员的帮助.
需要另一个参数:启用.
以下固定的代码段添加了Enable class template参数.
编译器执行以下匹配:
>第一个参数U = int< – > X
>第二个参数V = bool< – > ÿ
> 3rd param Enable = int< – > enable< X> :: type(从第一个参数中推导出X)
(第3个参数是int,因为声明类Enable = U表示默认第3个参数与第1个参数相同)
修正片段:
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();
}