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