0

式のテンプレート化のためにオーバーライドする必要がある一連の演算子があります。基本型のすべての派生クラスが基本型に一致することを望みます。他のものは、ジェネリック型によってキャッチされます。残念ながら、ジェネリック型は基本型より先に派生型を取得します。分かりやすく混乱させるために、一部の 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)

4

2 に答える 2

1

クラスが何らかの種類であるかどうかをテストするトレイトを次に示しますBase

template<class T>
struct is_some_kind_of_Base {
    typedef char yes;
    typedef struct { char _[2]; } no;

    template<class U, class V>
    static yes test(Base<U, V> *);
    static no test(...);

    static const bool value = (sizeof(test((T*)0)) == sizeof(yes));
};

そして、後の 2 つoperator*の s を次のように制約します。

template <typename T1, typename T2,  typename R2>
typename boost::disable_if<is_some_kind_of_Base<T1>,
                MultOperation<Terminal<T1>, Base<T2, R2>, 
                              typename boost::common_type<T1, R2>::type> >::type
operator*( T1 const& u, Base<T2, R2> const& v) { /* ... */ }

デモ

common_typeハードエラーの発生を防ぐために、その評価を延期する必要があります。

template <class T1, class T2, class R1, class R2>
struct make_mult_operation {
    typedef MultOperation<T1, T2, typename boost::common_type<R1, R2>::type> type;
};

template <typename T1, typename T2,  typename R2>
typename boost::disable_if<is_some_kind_of_Base<T1>,
                make_mult_operation<Terminal<T1>, T2, T1, R2> >::type::type
operator*( T1 const& u, Base<T2, R2> const& v) { /* ... */ }

デモ

于 2015-05-12T23:45:10.357 に答える