2012-04-16 2 views
10

Скажем, у меня есть эти шаблоны псевдонимы:Является ли сбой замещения ошибкой с зависимыми параметрами шаблона не-типа?

enum class enabler {}; 

template <typename T> 
using EnableIf = typename std::enable_if<T::value, enabler>::type; 
template <typename T> 
using DisableIf = typename std::enable_if<!T::value, enabler>::type; 

я могу сделать следующее в НКУ:

#include <iostream> 

template <typename T, EnableIf<std::is_polymorphic<T>> = {}> 
void f(T) { std::cout << "is polymorphic\n"; } 

template <typename T, DisableIf<std::is_polymorphic<T>> = {}> 
void f(T) { std::cout << "is not polymorphic\n"; } 

struct foo { virtual void g() {} }; 

int main() { 
    f(foo {}); 
    f(int {}); 
} 

Он печатает:

полиморфный
не полиморфный

Что соответствует моим ожиданиям.

С clang этот код не компилируется. Он выдает следующие сообщения об ошибках.

test.cpp:11:58: error: expected expression 
template <typename T, EnableIf<std::is_polymorphic<T>> = {}> 
                 ^
test.cpp:14:59: error: expected expression 
template <typename T, DisableIf<std::is_polymorphic<T>> = {}> 
                 ^
test.cpp:20:3: error: no matching function for call to 'f' 
    f(foo {}); 
^
test.cpp:12:6: note: candidate template ignored: couldn't infer template argument '' 
void f(T) { std::cout << "is polymorphic\n"; } 
    ^
test.cpp:15:6: note: candidate template ignored: couldn't infer template argument '' 
void f(T) { std::cout << "is not polymorphic\n"; } 
    ^
test.cpp:21:3: error: no matching function for call to 'f' 
    f(int {}); 
^
test.cpp:12:6: note: candidate template ignored: couldn't infer template argument '' 
void f(T) { std::cout << "is polymorphic\n"; } 
    ^
test.cpp:15:6: note: candidate template ignored: couldn't infer template argument '' 
void f(T) { std::cout << "is not polymorphic\n"; } 
    ^
4 errors generated. 

Следует ли компилировать? Какой из двух компиляторов неисправен?

+0

Ой, я чувствую себя глупо. У меня такое чувство, что это не имеет ничего общего с псевдонимами шаблонов, поэтому заголовок, возможно, вводит в заблуждение: • Извините за это, я немного раскрою и исправлю заголовок, если это получится. –

+2

'DisableIf > = {}' - это инициализация списка инициализатора законного права? Могут ли структуры быть параметры шаблона? – jpalecek

+0

@jpalecek Нет, структуры не могут. Вот почему я использую enum :) –

ответ

7

Прежде всего, спасибо @Richard Smith на #llvm IRC Channel on oftc для объяснения.
К сожалению, это не законно C++ и как таковой Clang является правильным: {} не является выражение, но приготовился-INIT-лист и как таковые никогда не будет постоянного выражения, как требуется в инициализаторе несимметричный шаблонный параметр.

§14.3.2 [temp.arg.non-type] p1

шаблона аргумент для не-типа, нешаблонного шаблона параметр должен быть одним из:

  • для не-типа template- параметр интегрального или перечисляемого типа, преобразованное константное выражение (5.19) типа templat e-параметр; или
  • [...]

Одно решение было бы фиктивное значение в enabler.

+2

Это не хороший аргумент - мы здесь не говорим о аргументах шаблонов (никто не пытается, например, 'f '), но аргументы по умолчанию, которые имеют синтаксис объявления параметров, которые могут, в принципе, иметь '{ } 'на rhs (и если' enabler {} 'является константным выражением или' x', заданным 'enabler x {}', не должно быть проблемы с константой). Однако в 8.3.6/3 указано, что должно быть выражение в случае объявления параметра шаблона. – jpalecek

+0

@jpalecek: «oone пытается, например,' f '' Uh, вызывая 'f ' делает * точно *, что. – GManNickG

+1

@GManNickG: Нет, это не так. Параметры по умолчанию не указываются (по крайней мере явно) в виде текстовых замещений. – jpalecek