2016-08-08 3 views
5

При использовании SFINAE выбрать конструктор перегрузкам в прошлом, я обычно используются следующие:Как работает эллипс для SFINAE?

template <typename T> 
class Class { 
public: 
    template <typename U = T, typename std::enable_if<std::is_void<U>::value, int>::type=0> 
    Class() { 
     std::cout << "void" << std::endl; 
    } 

    template <typename U = T, typename std::enable_if<!std::is_void<U>::value, int>::type=0> 
    Class() { 
     std::cout << "not void" << std::endl; 
    } 
}; 

Однако, я просто наткнулся на эту альтернативу:

template <typename U = T, typename std::enable_if<std::is_void<U>::value>::type...> 
Class() { 
    std::cout << "void" << std::endl; 
} 

Учитывая, что следующее является незаконным. ..

template <typename U = T, void...> // ERROR! 
Class() { } 

... как работает альтернатива выше, используя эллипсы, а не аргумент шаблона непигового типа?


Полный код: http://coliru.stacked-crooked.com/a/64a1aaf13ce6099b

+0

@peppe Но 'template ' также является незаконным. Разве это не нужно использовать 'void' в качестве аргумента по умолчанию для параметра типа? Как и в, 'template :: type>'? – zennehoy

+1

@peppe В качестве параметра шаблона * type *, а не в качестве параметра шаблона шаблона. – Barry

+0

@Barry: IOW 'template :: type>' является незаконным, потому что он будет выводить 'void', если' condition' истинно, так как это параметр не-типа, а 'template :: type> 'является законным? – peppe

ответ

1

Мой предыдущий ответ был неправильным. Сожалею. Я просто исправлю это. не


Эта декларация:

template <typename U = T, void...> 
Class() { } 

нарушает [temp.res]/8:

Программа плохо формируется, никаких диагностических требуется, если [...] каждая действительная специализация вариационного шаблона требует пустого шаблона параметров пакета

Это не требуется диагностика, но компилятор все равно решает выпустить его. В любом случае, код плохо сформирован.

С другой стороны

template <typename U = T, std::enable_if_t<std::is_void<U>::value>...> 
Class() { } 

не нарушает это требование. У нас есть пустой пакет, поэтому мы не сталкиваемся с тем фактом, что вы не можете использовать void в качестве параметра шаблона непигового типа. Кроме того, гипотетическая специализация enable_if может обеспечить тип, который не является void, поэтому он не плохо сформирован из-за вышеуказанного ограничения.

+0

Я протестировал код с помощью 'enable_if_t <..., int>', и clang также не компилирует его, обвиняя как' Class2 ', так и 'Class2 ', чтобы быть неоднозначным. Не уверен, что если кто-то прав, то ... –

+1

@ W.F. Это известная ошибка, зафиксированная на багажнике IIRC. –

+0

@zennehoy Я знаю, что вы уже приняли мой ответ, но я не уверен, что это было неправильно, поэтому я изменил его. Сожалею. – Barry

Смежные вопросы