use*_*486 6 c++ templates scope-resolution
假设我有模板化的类
#include <iostream>
class A1 {
public:
int x{314159};
};
template<typename Context>
class A2 : public Context {};
template<typename Context>
class A3 : public Context {};
template<typename Context>
class A4 : public Context {
public:
int func() {
return Context::A1::x;
}
int gunc() {
return this->A1::x;
}
int hunc() {
return A1::x;
}
};
int main() {
A4<A3<A2<A1>>> my_A;
std::cout << "x = func() = " << my_A.func() << std::endl;
std::cout << "x = gunc() = " << my_A.gunc() << std::endl;
std::cout << "x = hunc() = " << my_A.hunc() << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
在模板化类的定义内部A4
,至少当仅使用实例类型时A4<A3<A2<A1>>>
,似乎可以将其x
称为
this->A1::x;
Run Code Online (Sandbox Code Playgroud)
要么
Context::A1::x;
Run Code Online (Sandbox Code Playgroud)
要么
A1::x;
Run Code Online (Sandbox Code Playgroud)
问题1:这些是否相等?好吧,我认为从A4
孤立地查看模板化类的角度来看,它们并不等效。为了Context::A1::x
正常工作,其模板参数应包含x
。为了this->A1::x
起作用,它应该包含一个称为的范围A1
,而该范围又应包含一个x
。而对于A1::x
工作的范围A4
本身就应该包含一个名为范围A1
包含x
。我的目的是从类型的角度询问它们是否等效 A4<A3<A2<A1>>>
。
注意: gcc 8.2 -O03 -std=c++17
在每种情况下都会产生相同的汇编代码。也就是说,我仅使用函数func
,gunc
和hunc
以及对相应函数的一个调用来编译代码,并且此编译器生成了相同的可执行文件。当然,严格来说,这不一定意味着对于抽象语言而言,这些表达是等效的。
问题2:x
在每种情况下如何“展开”工作范围?也许这个问题没有道理,或者不完全是我要问的问题。特别是如果对问题1的回答是等同的。在找到有关问题1的更多信息之后,请允许我修改此问题,或者先忽略此问题。
对问题2的注释:此观察结果可以阐明为什么我不确定拆包的工作方式。如果在模板化类中A4
我们还有一个方法
int iunc() {
return Context::Context::A1::x;
}
Run Code Online (Sandbox Code Playgroud)
然后编译失败
memberTemplatedParent.cpp: In instantiation of ‘int A4<Context>::iunc() [with Context = A3<A2<A1> >]’:
memberTemplatedParent.cpp:48:45: required from here
memberTemplatedParent.cpp:37:22: error: no type named ‘Context’ in ‘class A3<A2<A1> >’
return Context::Context::A1::x;
^
Run Code Online (Sandbox Code Playgroud)
因此,至少gcc
在A4
创建的类型实例时,其模板参数的template参数不是有效名称(或者我在中未正确命名Context::Context::A1::x
)。
问题1和2:
对于您选择的实例化,所有版本都是等效的。只要不歧义,就可以x
直接使用该成员,而无需指定范围。如果该成员不在当前类中,则检查基类,依此类推。
如果您指定特定的基类并且该成员x
不存在,则将再次查询该基类。
对于您的特定专业,您有
class A2<A1> : public A1 {};
class A3<A2<A1>> : public A2<A1>{};
class A4<A3<A2<A1>>> : public A3<A2<A1>> {
public:
int func() {
return A3<A2<A1>>::A1::x; // fine: search for x in A1,
// where A1 is searched in A3<A2<A1>>
}
int gunc() {
return this->A1::x; // fine: why not specifying A1 directly. The this pointer
// is not required here but adding does not cause any harm.
}
int hunc() {
return A1::x; // fine: why not specifying A1 directly.
}
int iunc() {
return x; // fine: would be possible as well
}
Run Code Online (Sandbox Code Playgroud)
};
最后一个问题:
int iunc() {
return Context::Context::A1::x;
}
Run Code Online (Sandbox Code Playgroud)
模板实例化后内容如下
int iunc() {
return A3<A2<A1>>::Context::A1::x;
}
Run Code Online (Sandbox Code Playgroud)
A3<A2<A1>>
编译器现在抱怨引入 name 的类中没有 typedef Context
。模板参数仅在类模板内可见。