我可以给你一个解决方法。
template <typename... TFs>
struct overload_set : TFs...
{
overload_set(TFs... fs) : TFs(fs)... {}
};
在这里,我们继承了一堆不同的父类型,每个都有一个operator()
。这些不会(至少在 gcc 中)按照您想要的方式重载。
为了解决这个问题,我们线性继承并进位()
向下通过using
:
template<class...Ts>
struct inherit_linearly;
template<>
struct inherit_linearly<>{};
template<class T0, class...Ts>
struct inherit_linearly<T0, Ts...>:
T0, inherit_linearly<Ts...>
{
using T0::operator();
using inherit_linearly<Ts...>::operator();
template<class A0, class...As>
inherit_linearly( A0&&a0, As&&...as ):
T0(std::forward<A0>(a0)),
inherit_linearly<Ts>(std::forward<As>(as)...)
{}
};
现在我们替换overload_set
如下:
template <typename... TFs>
struct overload_set : inherit_linearly<TFs...>
{
using inherit_linearly<TFs...>::operator();
overload_set(TFs... fs) :
inherit_linearly<TFs...>(std::forward<TFs>(fs)...)
{}
};
gcc 和 clang 都应该喜欢它。
线性继承不是最优的:平衡二叉树更好,但需要更多工作。 (基本上,你拿一包Xs...
你把它分成Xs_front...
and Xs_back...
使用小心的 TMP,将它们放入types<...>
打包,将它们转录给你的两个父母,然后做using blah::operator()
事物)。这是因为编译器对递归模板实例化和继承深度有限制,该限制往往比总模板实例化和继承“量”的限制更浅。
In c++17 /questions/tagged/c%2b%2b17我们不必进行这种线性继承:
template <typename... TFs>
struct overload_set : TFs...
{
using TFs::operator()...;
overload_set(TFs... fs) : TFs(fs)... {}
};
因为他们增加了一个你可以做的新地点...
扩张。