16

我注意到 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 标准中的以下措辞涵盖了这一点:

[温度.dep.type]/8

一个类型是依赖的,如果它是

  • 一个 simple-template-id,其中模板名称是模板参数或任何模板参数是依赖类型或依赖于类型或值的表达式

[温度.dep.expr]/4

以下形式的表达式从不依赖类型(因为表达式的类型不能依赖):

sizeof unary-expression
sizeof ( type-id )

[temp.dep.constexpr]/2

如果一元表达式或表达式是类型相关的或类型 ID 是相关的,则以下形式的表达式是值相关的:

sizeof unary-expression
sizeof ( type-id )

我的解释是sizeof(T)永远不能依赖于类型,意思sizeof(sizeof(T))永远不能依赖于类型或依赖于值。

这是gcc中的错误吗?

4

1 回答 1

7

我正在使用 N4296 后的草稿。

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

typename如果嵌套名称说明符 I<..>依赖于模板参数 [temp.res]/5,则需要。那么,是I<..>依赖吗?

[temp.dep.type]/9 一个类型是依赖的,如果它是

  • [...]
  • (9.7) 一个simple-template-id,其中模板名称是模板参数或任何模板参数是依赖类型或依赖于类型或值的表达式[ ...]

I<..>是一个simple-template-id,模板参数是一个表达式。这个表达式是sizeof(sizeof(T))类型相关的还是值相关的?

该表达式sizeof(sizeof(T))可以分解为以下表达式:

表达形式
================================================
              T       type-id 
       sizeof(T) sizeof ( type-id )
      (sizeof(T)) (表达式)
sizeof(sizeof(T)) sizeof一元表达式

T不是一个表达式,但我会把它留在列表中以备后用。关于括号的注释:primary-expression可以是带括号的(通用)表达式。一元表达式可以是一个后缀表达式,它可以是一个主表达式,因此它也可以用括号括起来。

带括号的表达式(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如果一元表达式表达式是类型相关的或类型 ID是相关的,则以下形式的表达式是值相关的:

sizeof unary-expression
sizeof ( type-id )
表达形式价值深度?类型深度?
==================================================== ======================
              T       type-id                    否 是
       sizeof(T) sizeof ( type-id ) 是 否
      (sizeof(T)) (表达式) 是 否
sizeof(sizeof(T)) sizeof一元表达式    否 否

因为T类型相关的,所以sizeof(T)变成相关的。但是,因为(sizeof(T))不是类型依赖的,sizeof(sizeof(T))所以根本不依赖。

于 2014-12-30T22:39:34.907 回答