gcc 5.0 和 clang 3.6 都需要typename
以下示例中的关键字:
template<typename T>
struct B
{
typedef int Type;
};
template<int n>
struct A
{
typedef typename B<decltype(throw (int*)n)>::Type Throw;
typedef typename B<decltype(delete (int*)n)>::Type Delete;
};
C++11 标准中的以下措辞涵盖了这一点:
[除外]/2
throw 表达式的类型为 void。
[expr.delete]/1
操作数应具有指向对象类型的指针,或具有指向对象类型指针的单个非显式转换函数的类类型。结果类型为 void。
所以我假设在这两种情况下都会decltype
产生void
。
[expr.const]/2
条件表达式是核心常量表达式,除非它涉及以下之一作为潜在评估的子表达式
新表达
抛出表达式
这表明包含throw
或delete
不能是常量表达式的表达式。
[温度.dep.type]/8
一个类型是依赖的,如果它是
一个 simple-template-id,其中模板名称是模板参数或任何模板参数是依赖类型或依赖于类型或值的表达式
由 表示
decltype(expression)
,其中表达式依赖于类型
仅当表达式依赖于类型时, SoB<decltype(..)>
才依赖。
[温度.dep.expr]/4
以下形式的表达式从不依赖类型(因为表达式的类型不能依赖):
delete cast-expression throw assignment-expression
这表明两个表达式都不能依赖于类型。
gcc 和 clang 都错了吗?