4

(本题与C++11/C++14无关:示例使用C++03编译)

enable_bool<T>::type只有当T是时才有成员bool

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(when Tis bool)
,我们很想分解参数TEnable
但编译器抱怨(见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在上述部分特化中推导出模板参数?

4

1 回答 1

2

最后,这个问题甚至与 SFINAE 无关!

考虑这个没有 SFINAE 的非常简单的片段:
enable<T>::type总是与T提供的任何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

编译器的设计目的不是X从 equation推导出来int = enable<X>::type
因此,编译器需要开发者的一些帮助。
另一个参数是必需的:Enable.

下面的固定片段添加了Enable类模板参数。
编译器执行以下匹配:

  • 1st param U =int <--> X
  • 2nd param V =bool<--> Y
  • 3rd param Enable=int <--> enable<X>::type(从第一个参数推导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();
}
于 2015-10-09T07:44:25.940 回答