C++ 特定方法的编译时选择,伪装成运算符
我有一门课是这样的: 结构基 { 无效常数{ std::cout您可以这样编写Magic类:C++ 特定方法的编译时选择,伪装成运算符,c++,templates,operator-overloading,downcast,C++,Templates,Operator Overloading,Downcast,我有一门课是这样的: 结构基 { 无效常数{ std::cout您可以这样编写Magic类: struct Magic { Magic(Base &b) : b(b) {} Base &b; struct AA { Base &b; void operator*(int n) const { return b.aa(n); } };
struct Magic {
Magic(Base &b) : b(b) {}
Base &b;
struct AA {
Base &b;
void operator*(int n) const {
return b.aa(n);
}
};
struct BB {
Base &b;
void operator*(int n) const {
return b.bb(n);
}
};
AA as_AA() { return AA{b}; }
BB as_BB() { return BB{b}; }
};
这通过使用组合来避免任何继承。此外,数据对象没有副本,因为只对其进行了引用
现在,您可以完全使用所需的调用语法,并且它具有正确的行为:
Base data;
Magic obj(data);
obj.as_AA() * 33; // calls data.aa(33) -- prints 66
obj.as_BB() * 44; // calls data.bb(44) -- prints 176
这里有一个。使用相同函数名的一个解决方案是强键入参数:
struct AA {
int n;
};
struct BB {
int n;
};
void call(Base& base, AA arg) {
base.aa(arg.n);
}
void call(Base& base, BB arg) {
base.bb(arg.n);
}
...
Base data;
call(data, AA{33});
call(data, BB{44});
我冒昧地摆脱了操作符重载,因为它仍然使用相同的名称访问不同的实现
如果您试图通过使用相同的调用代码来进一步进行选择,您可以使用更高阶的函数:
auto call_aa(Base& base) {
return [&](int n) { return base.aa(n); };
}
auto call_bb(Base& base) {
return [&](int n) { return base.bb(n); };
}
...
Base data;
auto aa = call_aa(data);
aa(33);
call_bb(data)(44);
这也正是我实现代理类型的方式。感谢@cigien的回答。我考虑过这个解决方案,但我不确定,因为它创建了临时对象,并复制了对基本对象的引用。我想返回值优化会使它更好一些,但是…我正在寻找一个开销为0的解决方案。我使用的行,ch.as*44,在没有执行其他操作的情况下,真正解析为aa44,我认为引用是便宜的,所以这很好。我猜AA和BB在技术上是被复制的,但在-O2编译器似乎直接调用AA和BB。