嵌套 class 是 class 模板中的依赖类型?
Nested classes are dependent types in class templates?
考虑以下几点:
template<class> struct T
{
struct T1
{
struct T2
{
};
};
/*typename*/ T1::T2 m;
};
如果没有 typename
,编译将失败,因为 T2 被认为是从属名称,因此不是类型。在查看了 C++17 标准草案 (N4659) 之后,我相信我已经确定了原因:
§ 17.6.2.1 ¶ 5
A name is a member of the current instantiation if it is
— An unqualified name that, when looked up, refers to at least one member of a class that is the current instantiation or a non-dependent base class thereof.
...
A name is a dependent member of the current instantiation if it is a member of the current instantiation that, when looked up, refers to at least one member of a class that is the current instantiation.
T1 是当前实例化的依赖成员。 T2 不是当前实例化的成员(它是 T1 的成员),
§ 17.6.2.1 ¶ 9.3
A type is dependent if it is
...
— a nested class or enumeration that is a dependent member of the current instantiation,
...
T1 是一个嵌套的 class,因此是一个依赖类型。
§ 17.6 ¶ 3
When a qualified-id is intended to refer to a type that is not a member of the current instantiation (17.6.2.1) and its nested-name-specifier refers to a dependent type, it shall be prefixed by the keyword typename, forming a typename-specifier. ...
因此,需要typename
。
我的理解对吗?如果是这样,这背后的理由是什么? T1::T2
的查找怎么能找到除嵌套在 T1 中的 T2 之外的任何内容?
是的,你是对的。
在您的情况下,这无关紧要,因为您不可能在不实例化 m
的情况下专门化 T1
(因为它是 class 成员)。但是你可以这样做,将 m
放在一个函数中:
template<class> struct T
{
struct T1
{
struct T2
{
};
};
void foo() {
typename T1::T2 m;
}
};
template<>
struct T<void>::T1 {
int T2;
};
如果 T1
不相关,您的代码可能会改变含义,因为 T2
将引用值而不是类型。
考虑以下几点:
template<class> struct T
{
struct T1
{
struct T2
{
};
};
/*typename*/ T1::T2 m;
};
如果没有 typename
,编译将失败,因为 T2 被认为是从属名称,因此不是类型。在查看了 C++17 标准草案 (N4659) 之后,我相信我已经确定了原因:
§ 17.6.2.1 ¶ 5
A name is a member of the current instantiation if it is
— An unqualified name that, when looked up, refers to at least one member of a class that is the current instantiation or a non-dependent base class thereof.
...
A name is a dependent member of the current instantiation if it is a member of the current instantiation that, when looked up, refers to at least one member of a class that is the current instantiation.
T1 是当前实例化的依赖成员。 T2 不是当前实例化的成员(它是 T1 的成员),
§ 17.6.2.1 ¶ 9.3
A type is dependent if it is
...
— a nested class or enumeration that is a dependent member of the current instantiation,
...
T1 是一个嵌套的 class,因此是一个依赖类型。
§ 17.6 ¶ 3
When a qualified-id is intended to refer to a type that is not a member of the current instantiation (17.6.2.1) and its nested-name-specifier refers to a dependent type, it shall be prefixed by the keyword typename, forming a typename-specifier. ...
因此,需要typename
。
我的理解对吗?如果是这样,这背后的理由是什么? T1::T2
的查找怎么能找到除嵌套在 T1 中的 T2 之外的任何内容?
是的,你是对的。
在您的情况下,这无关紧要,因为您不可能在不实例化 m
的情况下专门化 T1
(因为它是 class 成员)。但是你可以这样做,将 m
放在一个函数中:
template<class> struct T
{
struct T1
{
struct T2
{
};
};
void foo() {
typename T1::T2 m;
}
};
template<>
struct T<void>::T1 {
int T2;
};
如果 T1
不相关,您的代码可能会改变含义,因为 T2
将引用值而不是类型。