【发布时间】:2019-07-26 00:04:09
【问题描述】:
假设我有模板类
#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 的作用域,其中包含一个x。 我的目的是从类型的角度询问它们是否等效 A4<A3<A2<A1>>>。
注意事项: 带有-O03 -std=c++17 的 gcc 8.2 在每种情况下都生成相同的汇编代码。也就是说,我只用func、gunc和hunc函数之一编译了代码,并且只调用了对应的函数,这个编译器产生了相同的可执行文件。当然,严格来说,这并不一定意味着对于抽象语言,这些表达式是等价的。
问题 2: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 的类型实例的那一刻,其模板参数的模板参数不是有效名称(或者我在@987654350 中没有正确命名) @)。
【问题讨论】:
-
这与奇怪重复的模板模式 (CRTP) 无关。详情见en.wikipedia.org/wiki/Curiously_recurring_template_pattern
-
@Handy999 谢谢。这个就是那个叫mixins的,这个名字对吗?
-
我不确定。
标签: c++ templates scope-resolution