Подтвердить что ты не робот

Конструкция в стиле конструктора в параметрах вызова функции

Я не понимаю, почему следующий код не удается скомпилировать при использовании конструкторского стиля:

template<typename T> void foo(const T& t){}

int main(){
  foo(unsigned char(0));
}

Ошибки:

  • error: expected primary-expression before ‘unsigned’ для gcc.
  • error: expected '(' for function-style cast or type construction для clang

Однако эти три синтаксиса верны:

template<typename T> void foo(const T& t){}

int main(){
  // c-style cast
  foo((unsigned char)0);

  // without unsigned
  foo(char(0));

  // aliased unsigned char
  typedef unsigned char uchar;
  foo(uchar(0));
}

Таким образом, здесь очевидно, что здесь висит пространство в типе.

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

template<typename T> void foo(const T& t){}

int main(){
  foo(unsigned char{0});
}

Но все же:

  • error: expected primary-expression before ‘unsigned’ для gcc.
  • error: expected '(' for function-style cast or type construction для clang

Итак, мой вопрос в том, почему не разрешено иметь тип, содержащий пробел в стилевом стиле? Это не выглядит двусмысленным для меня.

note: Я знаю, что могу написать foo<unsigned char>(0), но он не отвечает на вопрос;)

4b9b3361

Ответ 1

[C++11: 5.2.3/1]: Спецификатор простого типа (7.1.6.2) или typename-specifier (14.6), за которым следует заключенный в скобки список выражений, строит значение указанного типа с учетом списка выражений. [..]

Изучая грамматику, мы видим, что единственный способ получить unsigned char из производства спецификатора простого типа - это объединить два из них.

Как доказательство развенчания слуха о том, что в таблице 10 говорится об обратном, что я, возможно, сам начал недавно (: P), заголовок таблицы говорит "спецификатор (ы)" (обратите внимание на необязательное множественное число) и ссылается к следующему проходу:

[C++11: 5.2.3/2]: [..] В таблице 10 приведены допустимые комбинации спецификаторов простого типа и типы, которые они задают. (акцент мой)

Теперь в некоторых случаях допускается комбинирование спецификаторов простого типа:

[C++11: 7.1.6.2/3]: Если разрешено несколько спецификаторов простого типа, они могут свободно перемешаться с другими спецификаторами-объявлениями в любом порядке. [..]

& hellip; но нет никаких указаний на то, что это имеет место с функциональной нотацией, в которой четко указано " a простой тип-спецификатор" — единственное число.

Поэтому GCC корректен, а Visual Studio ошибочен.

Что касается того, почему это так... ну, я не знаю. Я подозреваю, что мы можем придумать какой-то двусмысленный край, но Casey дает хорошее замечание в комментариях ниже, что позволяет это не соответствовать синтаксису вызова функции, поскольку имена функций не могут иметь пробелов в них.