Зависит ли выражение вызова функции с одним аргументом параметра шаблона, не являющимся типом, от типа?

И clang 3.6, и gcc 5.0 требуют typename в следующем примере:

template<typename T>
struct B
{
    typedef int Type;
};

void f(int);

template<int n>
struct A
{
    typedef typename B<decltype(f(n))>::Type Type;
};

Это описано в следующей формулировке стандарта C++11:

[temp.dep.type]/5

Имя является членом неизвестной специализации, если оно

  • Квалифицированный идентификатор, в котором спецификатор вложенного имени называет зависимый тип, который не является текущим экземпляром.

[temp.dep.type]/8

Тип зависим, если он

  • член неизвестной специализации,

  • идентификатор простого шаблона, в котором либо имя шаблона является параметром шаблона, либо любой из аргументов шаблона является зависимым типом или выражением, зависящим от типа или значения.

  • обозначается decltype(expression), где выражение зависит от типа

Это предполагает, что B<decltype(f(n))>::Type зависит от типа, только если B<decltype(f(n))> зависит от типа. Также, что B<decltype(f(n))> зависит, только если f(n) зависит от типа.

[temp.dep.expr]/1

За исключением случаев, описанных ниже, выражение зависит от типа, если любое подвыражение зависит от типа.

[temp.dep.expr]/3

Идентификационное выражение зависит от типа, если оно содержит

  • идентификатор, связанный поиском имени с одним или несколькими объявлениями, объявленными с зависимым типом,

  • идентификатор шаблона, который является зависимым,

  • идентификатор функции преобразования, указывающий зависимый тип, или

  • спецификатор вложенного имени или квалифицированный идентификатор, который называет члена неизвестной специализации;

или если он называет статический элемент данных текущего экземпляра, который имеет тип «массив неизвестной границы T» для некоторого T

Это предполагает, что f(n) зависит от типа, только если n зависит от типа, и что n не зависит от типа.

Я что-то упустил, или это ошибка компилятора?


person willj    schedule 31.12.2014    source источник
comment
То же самое происходит при замене f(n) на *new int(n), который не зависит от типа в соответствии с [temp.dep.expr]/3.   -  person willj    schedule 31.12.2014


Ответы (1)


Ваш анализ немного неполный, но в остальном правильный.

Когда квалифицированный-id предназначен для ссылки на тип, который не является членом текущего экземпляра (14.6.2.1), а его описатель вложенного имени ссылается на зависимого типа, перед ним должно стоять ключевое слово typename, образующее спецификатор имени типа.

Ясно, что B<…>::Type не может относиться к члену текущего экземпляра. Итак, вопрос в том, является ли B<decltype(f(n))> зависимым типом.

Тип зависим, если он

  • […]
  • член неизвестной специализации,
  • […]
  • simple-template-id, в котором либо имя шаблона является параметром шаблона, либо любой из аргументов шаблона является зависимым типом или выражением, зависящим от типа или значения, или
  • обозначается decltype(expression), где выражение зависит от типа (14.6.2.2).

f(n) не зависит от типа, как никакое подвыражение, следовательно, decltype(f(n)) не является зависимым типом.
Кроме того, decltype(...) не может зависеть от значения, так как это не постоянное выражение1 и никакие другие абзацы в [temp.dep.constexpr] не применяются. Очевидно, что decltype(f(n)) также не зависит от типа.
И не в последнюю очередь, B<decltype(f(n))>::Type будет членом неизвестной специализации только в том случае, если аргумент шаблона будет зависимым типом2, который мы пришли к выводу. нет.

Таким образом, в моей интерпретации компиляторы неверны, и ключевое слово typename не требуется.


1 На самом деле decltype(…) вообще не выражение.

2 [temp.dep.type]/5:

Имя принадлежит неизвестной специализации, если оно

  • Квалифицированный идентификатор в котором описатель вложенного имени называет зависимый тип, который не является текущим экземпляром.
  • квалифицированный идентификатор, в котором описатель вложенного имени относится к текущему экземпляру, текущий экземпляр имеет по крайней мере один зависимый базовый класс, и поиск имени квалифицированного идентификатора не находит ни одного члена класса, который является текущим экземпляром, или его независимым базовым классом.
  • An id-expression denoting the member in a class member access expression (5.2.5) in which either
    • […]
person Columbo    schedule 31.12.2014