Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/128.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 特定方法的编译时选择,伪装成运算符_C++_Templates_Operator Overloading_Downcast - Fatal编程技术网

C++ 特定方法的编译时选择,伪装成运算符

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); } };

我有一门课是这样的:

结构基 { 无效常数{ 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 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。