为什么SFINAE需要'Enable'类模板参数?

时间:2015-10-07 16:51:33

标签: c++ template-specialization sfinae class-template

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

仅当IDictionary<long, IEnumerable<long, MyType>>enable_bool<T>

时,

::type才会有T成员

bool

在下一个代码段中,部分特化是正确的(请参阅gcc.godbolt.org

template <class T>
struct enable_bool
{};

template <>
struct enable_bool< bool >
{ typedef bool type; };

由于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相对应(TT时) 我们很想对参数boolT进行分解 但编译器抱怨(见gcc.godbolt.org

Enable

为什么编译器无法在上面的部分特化中推导出模板参数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; } };

1 个答案:

答案 0 :(得分: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 =&gt;无法推断X
  • 2nd param V = bool <--> Y

编译器的目的不是从等式X推导出int = enable<X>::type 因此,编译器需要开发人员的帮助 需要另一个参数:Enable

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

  • 1st param U =int <--> X
  • 2nd param V =bool<--> Y
  • 3rd param Enable=int <--> enable<X>::type(从第一个参数中推断出X
    (第3个参数是int,因为声明class 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();
}