假设我有模板类
#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;
}
在模板化类的定义内部A4
,至少在只使用实例类型时A4<A3<A2<A1>>>
,似乎可以引用x
为
this->A1::x;
或者
Context::A1::x;
或者
A1::x;
问题1:这些是等价的吗?A4
好吧,我想我可以从孤立地查看模板类的角度来看它们并不等同。为了Context::A1::x
工作,它的模板参数应该包含一个x
. 为了this->A1::x
工作,它应该包含一个名为 的范围A1
,而该范围又应该包含一个x
. 并且为了A1::x
工作,A4
其自身的范围应该包含一个名为A1
contains的范围x
。我的意图是从 type 的角度询问它们是否等效 A4<A3<A2<A1>>>
。
注意: gcc 8.2 with-O03 -std=c++17
在每种情况下都产生相同的汇编代码。也就是说,我只用函数func
,gunc
和hunc
只调用了对应的函数之一来编译代码,这个编译器生成了相同的可执行文件。当然,严格来说,这并不一定意味着对于抽象语言,这些表达式是等价的。
问题二:x
在每种情况下,作品范围的“拆包”是如何进行的?也许这个问题没有意义,或者不是我想问的。特别是如果问题 1 的答案是它们是等价的。请允许我在找到有关问题 1 的更多信息后修改此问题,或先忽略此问题。
问题 2 的注释:这个观察结果可能会澄清为什么我不确定拆包是如何工作的。如果在模板类中A4
我们还有一种方法
int iunc() {
return Context::Context::A1::x;
}
然后编译失败
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;
^
所以,至少在创建gcc
类型实例的那一刻,A4
它的模板参数的模板参数不是一个有效的名称(或者我没有在 中正确命名Context::Context::A1::x
)。