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

Может ли sizeof вложенное дважды быть зависимым выражением?

Я заметил, что gcc 5.0 отвергает следующий код, в то время как clang 3.6 принимает его.

template<int n>
struct I
{
    typedef int Type;
};

template<typename T>
struct A
{
    typedef I<sizeof(sizeof(T))>::Type Type;
};

Кажется, что два компилятора отличаются от того, является ли sizeof(sizeof(T)) зависимым от типа или зависящим от значения выражением. Если выражение было зависимым, то следует, что I<sizeof(sizeof(T))> является зависимым типом, что означает необходимость typename.

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

[temp.dep.type]/8

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

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

[temp.dep.expr]/4

Выражения следующих форм никогда не зависят от типа (поскольку тип выражения не может быть зависимый):

sizeof unary-expression
sizeof ( type-id )

[temp.dep.constexpr]/2

Выражения следующей формы зависят от стоимости, если унитарное выражение или выражение являются независимыми или идентификатор типа зависит:

sizeof unary-expression
sizeof ( type-id )

Моя интерпретация заключается в том, что sizeof(T) никогда не может быть зависимым от типа, то есть sizeof(sizeof(T)) никогда не может быть зависимым от типа или зависящим от значения.

Является ли это ошибкой в ​​gcc?

4b9b3361

Ответ 1

Я использую проект post-N4296.

typedef I<sizeof(sizeof(T))>::Type Type;

typename требуется, если спецификатор вложенных имен I<..> зависит от параметра шаблона [temp.res]/5. Итак, I<..> зависит?

[temp.dep.type]/9 Тип зависит, если он

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

I<..> - это простой шаблон-id, аргумент шаблона - выражение. Является ли это выражение sizeof(sizeof(T)) зависимым от типа или зависящим от значения?

Выражение sizeof(sizeof(T)) можно разбить на следующие выражения:

expression           form
===============================================
              T      type-id
       sizeof(T)     sizeof ( type-id )
      (sizeof(T))    ( expression )
sizeof(sizeof(T))    sizeof unary-expression

T не является выражением, но я оставлю его в списке позже. Примечание в круглых скобках: первичное выражение может быть выражением в скобках (общее). Унарное выражение может быть постфиксным выражением, которое может быть основным выражением, поэтому оно также может быть заключено в круглые скобки.

Обозначенное в скобках выражение (X) зависит, если X зависит:

[temp.dep.expr]/1 За исключением случаев, описанных ниже, выражение зависит от типа, если любое подвыражение зависит от типа.

[temp.dep.constexpr]/1 За исключением случаев, описанных ниже, константное выражение зависит от значения, если любое подвыражение зависит от значения.

В общем случае выражения sizeof никогда не являются типа -зависимыми, поскольку они всегда выдает значение типа std::size_t:

[temp.dep.expr]/4 Выражения следующих форм никогда не зависят от типа (поскольку тип выражения не может быть зависимым):

[...]
sizeof unary-expression
sizeof ( type-id )

Однако значение, которое они дают, может зависеть от параметра шаблона:

[temp.dep.constexpr]/2 Выражения из следующей формы зависят от значения, если унитарное выражение или выражение зависят от типа или идентификатор типа:

sizeof unary-expression
sizeof ( type-id )
expression           form                       value-dep?   type-dep?
=======================================================================
              T      type-id                    no           yes
       sizeof(T)     sizeof ( type-id )         yes          no
      (sizeof(T))    ( expression )             yes          no
sizeof(sizeof(T))    sizeof unary-expression    no           no

Так как T тип -зависимый, sizeof(T) становится значением -зависимым. Однако, поскольку (sizeof(T)) не тип -зависимый, sizeof(sizeof(T)) вообще не зависит.