可以将嵌套两次的sizeof作为依赖表达式吗?

时间:2014-12-30 22:02:40

标签: c++ templates language-lawyer dependent-type compiler-bug

我注意到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

     

如果类型是

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

[temp.dep.expr / 4

     

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

sizeof unary-expression
sizeof ( type-id )
     

[temp.dep.constexpr] / 2

     

如果一元表达式或表达式是类型依赖的,则以下形式的表达式是值依赖的   或者type-id是依赖的:

sizeof unary-expression
sizeof ( type-id )

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

这是gcc中的错误吗?

1 个答案:

答案 0 :(得分:7)

我正在使用N4296之后的草稿。

typedef I<sizeof(sizeof(T))>::Type Type;
如果嵌套名称说明符 typename依赖于模板参数[temp.res] / 5,则需要

I<..>。那么,I<..>依赖吗?

  

[temp.dep.type] / 9如果类型是

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

I<..> simple-template-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不是表达式,但我会将其留在列表中以供日后使用。括号中的注释: primary-expression 可以是带括号的(常规)表达式一元表达式可以是 postfix-expression ,它可以是 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如果一元表达式表达式与类型有关,则以下形式的表达式是值依赖的或 type-id 依赖

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))根本不依赖。