Вопрос по c++, c++11 – Является ли ошибка замещения ошибкой с зависимыми нетиповыми параметрами шаблона?

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;

Я могу сделать следующее в GCC:

#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 {});
}

Это печатает:

is polymorphic
is not polymorphic

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

С 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.

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

Упс, я чувствую себя глупо. У меня такое ощущение, что это не имеет ничего общего с псевдонимами шаблонов, поэтому заголовок, возможно, вводит в заблуждение: S Извините, я немного исследую и исправлю заголовок, если это окажется так. R. Martinho Fernandes
DisableIf<std::is_polymorphic<T>> = {} это легальная инициализация списка инициализации? Могут ли структуры быть параметрами значения шаблона? jpalecek
Clang выдает похожие сообщения об ошибках, если я не использую псевдонимы и просто вручную "inline" их, поэтому я исправил заголовок. R. Martinho Fernandes
@jpalecek Это для перечисленийname, Это относится к тому факту, чтоenum {} действителен, ноenum class {} ISN & APOS; т. Совсем не уместно здесь. R. Martinho Fernandes
@jpalecek Нет, структуры не могут & t; Вот почему я использую перечисление :) R. Martinho Fernandes

Ваш Ответ

1   ответ
7

First and foremost, thanks to @Ричард Смит на#llvm IRC канал на oftc для объяснения.
К сожалению, это недопустимый C ++, и поэтому Clang является правильным:{} это не выражение, аbraced-init-list и как таковой никогда не будетconstant выражение, необходимое для инициализации не типового параметра шаблона.

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

A template-argument for a non-type, non-template template-parameter shall be one of:

  • for a non-type template-parameter of integral or enumeration type, a converted constant expression (5.19) of the type of the template-parameter; or
  • [...]

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

@GManNickG: нет, это не так. Параметры по умолчанию не указываются (по крайней мере явно) в качестве текстовых подстановок.
@jpalecek Является ли абзац 9 из 14.1 «Параметры шаблона» & quot; Adefault template-argument этоtemplate-argument (14.3) указано после= вtemplate-parameter. & Quot; недостающий аргумент в этом случае?
Это не хороший аргумент - мы не говорим здесь о аргументах шаблона (никто не пытается, например.f<int,{}>), но аргументы по умолчанию, которые имеют синтаксис объявления параметра, который в принципе может иметь{} на правой (и еслиenabler{} является постоянным выражением, илиx, даноenabler x{}не должно быть проблем с константой). Однако, 8.3.6 / 3 говорит, что должно быть выражение в случае объявления параметров шаблона.
@jpalecek: Чем аргумент по умолчанию отличается от формального аргумента? В любом случае вы не можете просто использовать{} потому что это никогда не может быть константным выражением, которое необходимо для инициализации не типового параметра.
@jpalecek: "один пытается, например.f<int,{}>& Quot; Звонюf<int> делаетexactly тот.

Похожие вопросы