式のテンプレート化のためにオーバーライドする必要がある一連の演算子があります。基本型のすべての派生クラスが基本型に一致することを望みます。他のものは、ジェネリック型によってキャッチされます。残念ながら、ジェネリック型は基本型より先に派生型を取得します。分かりやすく混乱させるために、一部の 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::enable_if
たが、私の試みはすべて行き詰まりにつながりました。さて、目標は式のテンプレートであることを覚えておいてください。そのため、入ってくるデータのキャストを行うことはできません.ええ...とても複雑です.あなたがいくつかの魔法を持っていることを願っています.
質問の短いバージョン:最初の演算子と2 番目の演算子(1 * Derived) * Derived
を一致させる
にはどうすればよいですか? T は変換を行わないため、Base よりも適切に一致するため、現在は最初の罰金に一致し、次に 2 番目の一致が代わりに Base-generic 演算子の 1 つに一致します。operator(T, Base)
operator(Base, Base)