2017-01-13 7 views
1

私は現在テンプレートメタプログラミングで遊んでいます。私はtmpを使って有限状態マシンを作ろうとしています。私はWebにいくつかの実装があることを知っていますが、私は自分自身を実装として実装したいと思います。C++テンプレートメタプログラミング:オーバーロード演算子

私はベースクラス内のテンプレートベースクラスのテンプレート派生派生の演算子をオーバーロードしようとしています。その派生の

template<typename Input> 
class Base 
{ 
public: 
    virtual ~Base() = default;  
    virtual bool operator()(const Input& input) const = 0; 

    template<typename Lhs, typename Rhs> 
    constexpr Derivation1<Input, Lhs, Rhs> operator||(const Lhs& left, const Rhs& right) const; 

    template<typename Lhs, typename Rhs> 
    constexpr Derivation2<Input, Lhs, Rhs> operator&&(const Lhs& left, const Rhs& right) const; 
}; 

と2:

template<typename Input, typename... TSpecialized> 
class Derivation1 : public Base<Input> 
{ 
public: 
    bool operator()(const Input& input) const override 
    { 
     // ... 
    } 
}; 

template<typename Input, typename... TSpecialized> 
class Derivation2 : public Base<Input> 
{ 
public: 
    bool operator()(const Input& input) const override 
    { 
     // ... 
    } 
}; 

、我々は、基本クラスで宣言された演算子の定義:私たちは、基本クラスがあるとし

template <typename Input> 
template <typename Lhs, typename Rhs> 
constexpr Derivation1<Input, Lhs, Rhs> Base<Input>::operator||(const Lhs& left, const Rhs& right) const 
{ 
    return Derivation1<Input, Lhs, Rhs>(); 
} 

template <typename Input> 
template <typename Lhs, typename Rhs> 
constexpr Derivation2<Input, Lhs, Rhs> Base<Input>::operator&&(const Lhs& left, const Rhs& right) const 
{ 
    return Derivation2<Input, Lhs, Rhs>(); 
} 

種類RhsとLhsは基本クラスの派生物でもあります。

私はのような演算子を使用しよう:私はオペレーターの過負荷は、引数に一致しないというエラーを取得しています

Derivation3<int, 10, 20> left; 
Derivation4<int, 300, 290> right; 

auto result = left || right; 

。どちらの派生型も同じ基本型:Base<int>を持ち、オーバーロードを宣言する必要があります。変数resultは、Derivation1でなければなりません(上記のコードで宣言したように)。

この場合、オペラを正しくオーバーロードするにはどうすればよいですか?

+0

ありがとうございました。条件はベースを意味するタイプミスです。 Derivation3と4は、基底クラスの他の派生を表すため、正しいです。 Derivation1とDerivation2は、論理関数andと関数を実装する特殊なケースです。だから、彼らはこれらのオペレータによって返されます。 – Timo

答えて

3

解決策が見つかりました。私は、基本クラスでtypedefを作成しました:

template<typename Input> 
class Base 
{ 
public: 
    virtual ~Base() = default;  
    virtual bool operator()(const Input& input) const = 0; 

    typedef Input inputType; 
}; 

を、私はクラスの外で演算子オーバーロードを移動:

template <typename Lhs, typename Rhs> 
constexpr Derivation1<typename Lhs::inputType, Lhs, Rhs> operator||(const Lhs& left, const Rhs& right) 
{ 
    return Derivation1<typename Lhs::inputType, Lhs, Rhs>(); 
} 

template <typename Lhs, typename Rhs> 
constexpr Derivation2<typename Lhs::inputType, Lhs, Rhs> operator&&(const Lhs& left, const Rhs& right) 
{ 
    return Derivation2<typename Lhs::inputType, Lhs, Rhs>(); 
} 

意図したとおり、このコードは完璧に動作します。

+0

コンパイラが 'Base'で宣言されている関数を許可したのは驚くべきことです。そこには「友人」の指定子が必要でした。 – Potatoswatter

関連する問題