我正在阅读 C++ 中的“mixin”技术,但有一些我不明白的东西,似乎是语言的一个限制,由于编译器的歧义(和标准拒绝解决,甚至如果可以的话)。
mixin 的想法是聚合来自不同部分的能力。有时可以用相同的名称调用这些功能,因为它们通常做同样的事情。
struct A{
void f(int){}
};
struct B{
void f(double){}
};
我可以将这两个类的服务与
struct CombinedAB : A, B{};
但是,当我使用它时,我得到一个编译错误:“对成员 'f' 的请求不明确”(godbolt 链接)。
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++ 中组合类的正确方法吗?是否有解决方法,或者这只是对问题的过于幼稚的看法?如有必要,我愿意接受涉及大量模板代码的选项。
即使实例化不是等式的一部分并且f
是静态函数,问题仍然存在。似乎该语言对更改或组合基类中成员函数的含义有强烈的感觉。