снова о C ++ SFINAE в enable_if_t - PullRequest
       24

снова о C ++ SFINAE в enable_if_t

0 голосов
/ 03 декабря 2018

Я пытаюсь выяснить, почему SFINAE не работает с прямой инициализацией аргументов шаблона?

Это работает в этой форме, когда я объявляю другой параметр шаблона, здесь:

#include <iostream>

template <bool B, class T = void>
class enable_if {};

template <class T>
struct enable_if<true, T> {    typedef T type; };

template <bool B, class T>
using enable_if_t = typename enable_if<B,T>::type;

template< typename T >
struct Y {

public:
    template< typename U = T >
    enable_if_t<true, U>
    foo() {
        return 111;
    }

    template< typename U = T >
    enable_if_t<false, U>
    foo() {
        return 222;
    }
};

int main() {
    Y< double > y;
    std::cout << y.foo() << std::endl;
}

(печатает 111)

, но если я рефакторинг с этим синтаксисом, компилятор выдаст ошибку:

#include <iostream>

template <bool B, class T = void>
class enable_if {};

template <class T>
struct enable_if<true, T> {
    typedef T type;
};

template <bool B, class T>
using enable_if_t = typename enable_if<B,T>::type;

template< typename T >
struct Y {    
    template< typename U = enable_if_t<true, T> >
    U
    foo() {
        return 11;
    }

    template< typename U = enable_if_t<false, T> >
    U
    foo() {
        return 12;
    }
};

int main() {
    Y< double > y;
    std::cout << y.foo() << std::endl;
}

"Член класса не может быть повторно объявлен" Я предполагаю, что второй экземпляр сформированнедопустимо и должно быть исключено SFINAE?

И почему я не могу объявить foo () следующим образом:

enable_if_t<true, T> foo() { return 11; } 
enable_if_t<false, T> foo() { return 12; } 

, основываясь только на параметре T шаблона класса?второй enable_if_t не должен быть допустимым, а экземпляр foo () должен быть отброшен, верно?

1 Ответ

0 голосов
/ 03 декабря 2018

Во втором случае вы объявляете два метода класса:

template<typename U> U foo();

У вас не может быть двух методов класса шаблона с одинаковыми сигнатурами и именами, так же как вы не можете объявить два не шаблонных классаметоды с одинаковыми сигнатурами и именами:

int bar();

и

int bar();

Два ваших метода класса шаблонов имеют разные параметры шаблона по умолчанию, но это несущественно.Значения параметров шаблона по умолчанию не считаются частью подписи.СФИНА не вступает в игру здесь.SFINAE - это то, что происходит, когда происходит шаблон замена , часть "S", а не объявление.

...