我有一组运算符需要重写以进行表达式模板。我希望基类型的所有派生类都与基类型匹配。然后其他的东西会被泛型类型捕获。不幸的是,泛型类型在基类型之前获取派生类型。为了让事情变得美好和混乱,一切都被大量模板化,包括一些 CRTP。让我试着给出一个更简单的代码版本:
// Note: 'R' is used for return type
template <typename DerivedType, typename R>
class Base
{ // ...
};
template <typename E1, typename E2, typename R>
class MultOperation : public Base<MultOperation<E1, E2, R>, R>
{ // ...
};
template <typename T>
class Terminal : public Base<Terminal<T>, T>
{ // ...
};
// The broken operators:
template <typename T1, typename T2, typename R1, typename R2>
MultOperation<Base<T1, R1>, Base<T2, R2>, typename boost::common_type<R1, R2>::type>
operator*( Base<T1, R1> const& u, Base<T2, R2> const& v)
{
return MultOperation<Base<T1, R1>, Base<T2, R2>, typename boost::common_type<R1, R2>::type>(u, v);
}
template <typename T1, typename T2, typename R1, typename R2>
MultOperation<Terminal<T1>, Base<T2, R2>, typename boost::common_type<T1, R2>::type>
operator*( T1 const& u, Base<T2, R2> const& v)
{
return MultOperation<Terminal<T1>, Base<T2, R2>, typename boost::common_type<T1, R2>::type>(Terminal<T1>(u), v);
}
template <typename T1, typename T2, typename R1, typename R2>
MultOperation<Base<T1, R1>, Terminal<T2>, typename boost::common_type<R1, T2>::type>
operator*( Base<T1, R1> const& u, T2 const& v)
{
return MultOperation<Base<T1, R1>, Terminal<T2>, typename boost::common_type<R1, T2>::type>(u, Terminal<T2>, v);
}
现在,我不能使用任何新的 C++ 功能。(这是删除旧库的一些重构的一部分,因此我们可以升级到新的 cpp 标准。)不过,我可以使用 boost 的东西。我在想我的答案可能在于boost::enable_if
某些东西,但我所有的尝试都导致了死胡同。现在,请记住,目标是表达式模板,所以我不能为传入的数据做任何转换。是的......它太复杂了......我希望你有一些魔法。
问题的简短版本:
如何(1 * Derived) * Derived
匹配operator(T, Base)
第一个运算符,然后匹配operator(Base, Base)
第二个运算符?它目前匹配第一个罚款,然后第二个匹配一个 Base-generic 运算符,因为 T 不进行转换,因此比 Base 匹配得更好。