Я заметил, что 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
должно быть обязательно
На это распространяется следующая формулировка в стандарте C ++ 11:
[Temp.dep.type] / 8Тип зависит, если он
[Temp.dep.expr] / 4
- простой идентификатор шаблона, в котором имя шаблона является параметром шаблона или любой из шаблона
Аргументы являются зависимым типом или выражением, которое зависит от типа или значенияВыражения следующих форм никогда не зависят от типа (потому что тип выражения не может быть
зависимая):[Temp.dep.constexpr] / 2sizeof unary-expression sizeof ( type-id )
Выражения следующей формы зависят от значения, если унарное выражение или выражение зависит от типа
или идентификатор типа зависит:sizeof unary-expression sizeof ( type-id )
Моя интерпретация такова, что sizeof(T)
никогда не может зависеть от типа, то есть sizeof(sizeof(T))
никогда не может зависеть от типа или значения.
Это ошибка в GCC?
Я использую черновик после N4296.
typedef I<sizeof(sizeof(T))>::Type Type;
typename
требуется, если вложенное имя спецификатор I<..>
зависит от параметра шаблона [temp.res] / 5. Итак, это I<..>
зависит?
[temp.dep.type] / 9 Тип зависит, если он
- […]
- (9.7) простой шаблон-идентификатор в котором либо имя шаблона является параметром шаблона, либо любой из аргументов шаблона является зависимым
тип или выражение, которое зависящий от типа или же Значение-зависимого, или же
[…]
I<..>
это простой шаблон-идентификатор, Аргумент шаблона является выражением. Это выражение sizeof(sizeof(T))
зависит от типа или значения?
Выражение sizeof(sizeof(T))
можно разбить на следующие выражения:
форма выражения =============================================== T тип-идентификатор sizeof (T) sizeof ( тип-идентификатор ) (sizeof (T)) ( выражение ) sizeof (sizeof (T)) Унарное выражение
T
это не выражение, но я оставлю его в списке на потом. Примечание в скобках: A первичное выражение может быть заключен в скобки (общий) выражение. Унарное выражение может быть постфикс-выражение который может быть первичное выражение, следовательно, это также может быть заключено в скобки.
Выражение в скобках (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 )
Форма выражения value-dep? тип-DEP? ================================================== ===================== T тип-идентификатор нет да sizeof (T) sizeof ( тип-идентификатор ) да нет (sizeof (T)) ( выражение ) да нет sizeof (sizeof (T)) Унарное выражение нет нет
поскольку T
является тип-зависимая, sizeof(T)
становится значение-зависимый. Тем не менее, так как (sizeof(T))
является не тип-зависимая, sizeof(sizeof(T))
не зависит вообще.