2017-01-13 25 views
1

我目前正在玩模板元編程。我試圖通過使用tmp來創建一個有限狀態機。我知道網絡中有幾種實現方式,但我想自己實現一種實踐方式。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的類型(就像我們在上面的代碼中聲明的那樣)。

在這種情況下,我如何正確地重載operatros?

+0

謝謝。條件是意味着基地的錯字。 Derivation3和4是正確的,因爲它們代表基類的任何其他派生。 Derivation1和2是特殊情況,因爲它們實現邏輯或和和功能。這就是他們被這些運營商退回的原因。 – 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