Why does SFINAE require an enable class template parameter?

(this question is not related to C ++ 11 / C ++ 14: examples compiled using C ++ 03)

enable_bool<T>has a member ::typeonly when Tthere isbool

template <class T>
struct enable_bool
{};

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

In the following snippet, the partial specialization is correct (see 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();
}

Since it enable_bool<T>::typealready matches T(when Tthere is bool),
we tend to factor the parameters Tand Enable.
But the compiler complains (see 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; }
};

Why can't the compiler output the template parameter Tin this partial specialization?

+4
1

, 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 int = enable<X>::type.
.
: Enable.

Enable.
:

  • 1st param U =int <--> X
  • 2nd param V =bool<--> Y
  • 3rd param Enable=int <--> enable<X>::type ( X 1- )
    ( 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();
}
+2

Source: https://habr.com/ru/post/1610623/


All Articles