将类(mixin)的功能与不明确的调用结合起来 我在阅读C++中的“Mixin”技术,但是有些东西我不理解,而且似乎是语言中的一个限制,它不能通用地做,因为编译器(和标准即使不能够解决)也存在歧义。

将类(mixin)的功能与不明确的调用结合起来 我在阅读C++中的“Mixin”技术,但是有些东西我不理解,而且似乎是语言中的一个限制,它不能通用地做,因为编译器(和标准即使不能够解决)也存在歧义。,c++,templates,mixins,ambiguous-call,template-mixins,C++,Templates,Mixins,Ambiguous Call,Template Mixins,mixin的思想是聚合来自不同部分的功能。 有时,这些功能可以用相同的名称调用,因为它们通常做相同的事情 struct A{ void f(int){} }; struct B{ void f(double){} }; 我可以把两个班的服务结合起来 struct CombinedAB : A, B{}; 但是,当我使用它时,我得到一个编译错误: 因此,编译器知道f存在,但它拒绝解析哪个是正确的调用。它会生成以下错误: main.cpp: In function ‘int m

mixin的思想是聚合来自不同部分的功能。 有时,这些功能可以用相同的名称调用,因为它们通常做相同的事情

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

struct B{
    void f(double){}
};
我可以把两个班的服务结合起来

struct CombinedAB : A, B{};
但是,当我使用它时,我得到一个编译错误:

因此,编译器知道
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
重载”

它是有效的,但问题是,
CombineAB
不能通用地完成。最接近的是:

template<class T1, class T2>
struct combination : T1, T2{
 // using T1::all_provided_by_T1;
 // using T2::all_provided_by_T2;
};
这与目的背道而驰,因为如果T1和T2提供了20个同名函数(在我的例子中),那么类将需要重复所有这些函数名。最糟糕的是,它不能通过额外的模板参数来完成(可以吗?)

<强>这是C++中组合类的正确方法吗?有没有解决办法,或者这只是问题的太幼稚的观点?如有必要,我愿意接受包含大量模板代码的选项。


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

我自己问题的部分答案:

事实上,我意识到这是“点”符号的一个特点,以及C++对这个语法的坚定性。 这似乎不是一个基本的限制,而是一个在语言中故意用来限制点符号使用的块。 也许这是与虚拟功能可能被误用有关的一个历史怪癖

我一放开“点”符号,mixin行为就突然可以用一个等价的(但有些出乎意料的)语法了

结构A{ 空f(int){} friendvoidf(A&self,inti){self.f(i);} }; 结构B{ 空f(双){} friendvoidf(B&self,双d){self.f(d);} }; 结构C:A,B{ //使用A::f; //使用B::f; }; 模板 结构组合:T1,T2{}; int main(){ C C; //c.f(5.1);//错误,调用不明确 f(c,5.1); 这一问题需要以某种方式加以解决。 这是我看到的第一种情况,强制使用
c.f(a)
符号从根本上说比强制使用
f(c,a)
符号更具限制性。 我的结论是mixin不能通过“点”符号工作。 遗憾的是,它也会影响静态成员函数(“:”符号)


如果有人知道的话,我仍然对使用“点”符号的一些技巧感兴趣。

您需要保存您想要的f:
CombinedAB c;c.B::f(3.14)是的,但这将迫使用户知道,
CombinedAB
是从
B
派生而来的。注意,
f
可以从参数类型中解析。(我知道这是标准行为,我正在寻找解决方法。)看一看类似问题的此答案您的更新看起来像一个答案。为什么不将其作为答案发布,而不是作为问题的更新发布?不,一点也不,只要没有可接受的答案,人们仍然会回答。最好将问题和任何答案分开。
struct CombineAB : A, B{
    using A::f;
    using B::f;
};
template<class T1, class T2>
struct combination : T1, T2{
 // using T1::all_provided_by_T1;
 // using T2::all_provided_by_T2;
};
template<class T1, class T2>
struct combination_of_f_service : T1, T2{
  using T1::f; using T2::f;
}
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);
}