c++ - 将类(mixins)的功能与歧义调用结合起来

标签 c++ templates mixins ambiguous-call template-mixins

我正在阅读有关C++中的“mixin”技术的信息,但由于某些原因,编译器(以及标准甚至拒绝解析,甚至无法解决)也使我无法理解,并且似乎在语言上存在局限性,无法通用地进行操作。如果可以)。
mixin的想法是聚合来自不同部分的功能。
有时可以使用相同的名称来调用功能,因为它们通常会执行相同的操作。

struct A{
    void f(int){}
};

struct B{
    void f(double){}
};
我可以将两个类的服务与
struct CombinedAB : A, B{};
但是,当我使用它时,出现编译错误:"request for member ‘f’ is ambiguous" (godbolt link)
CombinedAB c; c.f(3.14);  // 3.14 is a double, I expect B::f to be called.
因此,编译器知道f存在,但拒绝解析哪一个是正确的代码。它生成此错误:
main.cpp: In function ‘int main()’:
main.cpp:23:21: error: request for member ‘f’ is ambiguous
     CombinedAB c; c.f(3.14);
                     ^
main.cpp:16:10: note: candidates are: void B::f(double)
     void f(double){}
          ^
main.cpp:12:10: note:                 void A::f(int)
     void f(int){}
          ^
当然,我可以更改类并使用此惯用语“带来f重载的完整版本”。
struct CombineAB : A, B{
    using A::f;
    using B::f;
};
它可以工作,但是问题是CombineAB无法通用完成。最接近的是:
template<class T1, class T2>
struct combination : T1, T2{
 // using T1::all_provided_by_T1;
 // using T2::all_provided_by_T2;
};
但是我不能添加等效的using T1::f; using T2::f,首先,因为combination将需要了解T1,T2中的所有可能函数。
因此,似乎需要根据具体情况定义组合。例如与
template<class T1, class T2>
struct combination_of_f_service : T1, T2{
  using T1::f; using T2::f;
}
这没有达到目的,因为如果T1和T2提供20个具有相同名称的函数(如我的情况),则该类将需要重复所有这些函数的名称。最糟糕的是,无法通过其他模板参数来完成(可以吗?)。
这是在C++中组合类的正确方法吗?是否有解决方法?或者这仅仅是问题的幼稚 View ?如果需要,我愿意接受涉及很多模板代码的选项。

即使实例化不是方程式的一部分,并且f是静态函数,问题仍然存在。
该语言似乎对在基类中更改或组合成员函数的含义有强烈的感觉。

最佳答案

我的问题的部分答案:
实际上,我意识到这是“点”符号的特殊性,并且C++使用此语法是多么坚定。
它似乎不是一个基本的限制,而是在语言中故意限制了点符号的使用的一个块。
也许这是与可能滥用虚拟功能有关的历史怪癖。
一旦我放弃了“点”符号,就可以使用等效(但有些出乎意料)的语法突然实现mixin行为。

struct A{
    void f(int){}
    friend void f(A& self, int i){self.f(i);}
};

struct B{
    void f(double){}
    friend void f(B& self, double d){self.f(d);}
};

struct C : A, B{
//    using A::f;
//    using B::f;
};

template<class T1, class T2>
struct combination : T1, T2{};

int main(){
    C c;
//    c.f(5.1); // error, ambiguous call
    f(c, 5.1);

    combination<A, B> c2;
    f(c2, 5.1);
}
还有趣的是,如果此提议向前推进https://isocpp.org/blog/2016/02/a-bit-of-background-for-the-unified-call-proposal,则需要以某种方式解决此问题。
这是我看到的第一种情况,强制使用c.f(a)表示法从根本上比强制使用f(c, a)表示法更具局限性。
我的结论是,mixins无法通过“点”表示法工作。
遗憾的是,它也影响静态成员函数(“::”表示法)。
如果有人知道,我仍然会对使用“点”表示法的某种技术感兴趣。

关于c++ - 将类(mixins)的功能与歧义调用结合起来,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64130340/

相关文章:

c++ - 如何从字节序列构造 C++ 字符串?

C++ 套接字接受 block cout

django - 模型表单集和日期字段

html - 如何使用带有模块化比例的 SASS 为所有 header 生成尺寸

c++ - 如何在存在 2 个网卡的情况下为 UDP 多播设置套接字?

c++ - 二维数组问题-我收到错误 : expression must have pointer-to-object type (opencv, CUDA)

c++ - 使用字符串选择模板类的特化

c++ - 如何在编译时检查是否存在可以使用一组特定参数调用的函数?

html - 使用外部文件 W3.css 中的类创建 LESS mixin

ReactJS Reflux 在 ES6 中使用 mixin