在以下示例中,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标准中的以下措辞涵盖了这一点:
因此,我假设在两种情况下
decltype
都会生成void
。这表明涉及
throw
或delete
的表达式不能为常量表达式。因此,
B<decltype(..)>
仅在表达式依赖类型时才依赖。这表明两个表达式都不能依赖于类型。
gcc和clang都错了吗?
最佳答案
让我们回到需要typename
的时候。 §14.6[temp.res]/p3,所有引号均来自N4140:
在这种情况下,qualified-id是B<decltype(throw (int*)n)>::Type
(和delete
版本,其分析是完全相同的)。因此,如果nested-name-specifier或typename
引用从属类型,则B<decltype(throw (int*)n)>::
是必需的。
§14.6.2.1[temp.dep.type]/p8指出,省略了六个无关的项目符号,
B<decltype(throw (int*)n)>
是一个简单模板ID。模板名称B
不是模板参数。唯一的模板参数decltype(throw (int*)n)
不是表达式,因此,只有B<decltype(throw (int*)n)>
是从属类型时,decltype(throw (int*)n)
才是从属的。反之,按照子弹8.8,decltype(throw (int*)n)
仅在throw (int*)n
是类型相关的情况下才是相关的。但是我们知道,根据§14.6.2.2[temp.dep.expr]/p4:
因此,throw (int*)n
不依赖类型,因此decltype(throw (int*)n)
不是依赖类型,因此B<decltype(throw (int*)n)>
不是依赖类型,因此typename
不需要B<decltype(throw (int*)n)>::Type
,所以是的,这是一个编译器错误。
关于c++ - 抛出或删除表达式是否可以依赖?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/27713666/