嵌套两次的sizeof表达式可能是一个依赖表达式吗?

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 标准中包含以下措辞来涵盖此内容:

[temp.dep.type]/8

A type is dependent if it is

  • a simple-template-id in which either the template name is a template parameter or any of the template arguments is a dependent type or an expression that is type-dependent or value-dependent

[temp.dep.expr]/4

Expressions of the following forms are never type-dependent (because the type of the expression cannot be dependent):

sizeof unary-expression
sizeof ( type-id )

[temp.dep.constexpr]/2

Expressions of the following form are value-dependent if the unary-expression or expression is typedependent or the type-id is dependent:

sizeof unary-expression
sizeof ( type-id )

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

这是gcc的一个bug吗?


1
哦,GCC也认为sizeof n是相关的。http://melpon.org/wandbox/permlink/BLobLBzkQXNRfDuq - willj
有趣的是,在gcc 4.7.2上编译成功,但在4.9.0上失败了。 - Barry
@willj 这个改变有什么影响吗?sizeof(type-id) 仍然不是类型相关的。 - dyp
@dyp 加上更多的括号吧!而且 sizeof n 不受值限制,但 sizeof(T) 是受限于其类型的。这个新版本需要再加上一个 sizeof() 才能不再受限。 - willj
@Yakk 已经更正,谢谢。 - willj
显示剩余4条评论
1个回答

7
我正在使用一份N4296之后的草案。
typedef I<sizeof(sizeof(T))>::Type Type;

如果I<..>的嵌套名指定符依赖于模板参数[temp.res]/5,则需要typename。那么,I<..>是否相关?
引用块: [temp.dep.type]/9 如果类型是
  • [...]
  • (9.7) 简单模板ID,其中模板名称是模板参数或任何模板参数都是依赖类型或类型相关值相关的表达式 [...]
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 Expressions of the following forms are never type-dependent (because the type of the expression cannot be dependent):

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

然而,它们产生的价值可能取决于模板参数:

[temp.dep.constexpr]/2 Expressions of the following form are value-dependent if the unary-expression or expression is type-dependent or the type-id is dependent:

sizeof unary-expression
sizeof ( type-id )
表达式              形式                       值依赖?   类型依赖?
=======================================================================
              T      类型标识符                   否           是
       sizeof(T)     sizeof ( 类型标识符 )         是           否
      (sizeof(T))    ( 表达式 )                  是           否
sizeof(sizeof(T))    sizeof 单元运算表达式         否           否

由于T类型依赖的,所以sizeof(T)就变成了依赖的。然而,由于(sizeof(T))不是类型依赖的,所以sizeof(sizeof(T))根本没有依赖。


对于外部一对括号的提醒非常好。由于某种原因,我已经习惯了写sizeof(expression). - willj

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接