2016-01-08 25 views
0

我有幾個模板類的如何執行模板參數類從超派生使用匿名模板參數

template < class Cost > 
class Transition { 
    public: 
    virtual Cost getCost() = 0; 
}; 

template < class TransitionCl, class Cost > 
class State { 
    protected: 
     State(){ 
      static_assert(
       std::is_base_of< Transition<Cost>, TransitionCl >::value, 
       "TransitionCl class in State must be derived from Transition<Cost>" 
      ); 
     } 
    public: 
     virtual void apply(const TransitionCl&) = 0; 
}; 

,我寧可不要通過CostState,因爲State是完全獨立的Cost,但我想確保TransitionCl實現接口Transition

有沒有辦法在第二個模板中使Cost匿名,以便在聲明新的State類時不必傳遞它?

僅供參考,我使用g++ -std=c++14 [source file]

編輯:我張貼的問題的改寫(希望更清晰)版本,並獲得最佳答案here

回答

4

從我從你的問題的理解,在這裏是一個快速解決方案,我有:

template < class Cost > 
class Transition { 
    public: 
    virtual Cost getCost() = 0; 
}; 

template <typename T> 
class Der : public Transition<T> 
{ 
public: 
    T getCost() override { 
    } 
}; 

template < class Transition > 
class State; 

template <template <typename> class TransitionCl, typename Cost> 
class State <TransitionCl<Cost>> { 
public: 
     State(){ 
      static_assert(
       std::is_base_of< Transition<Cost>, TransitionCl<Cost> >::value, 
       "TransitionCl class in State must be derived from Transition<Cost>" 
      ); 
     } 
}; 

int main() 
{ 
    Der<int> d; 
    State<decltype(d)> s; 

    return 0; 
} 

在上面的示例中,您不必在創建狀態對象時傳遞'成本'類型。

===== UPDATE ======

template <typename Cost> 
class Transition 
{ 
public: 
    virtual Cost getCost() = 0; 
    virtual ~Transition() {} 
}; 

class TD: public Transition<int> 
{ 
public: 
    int getCost() override { 
     std::cout << "getCost override" << std::endl; 
     return 42; 
    } 
}; 

namespace detail { 
    template <typename T> 
    struct is_base_of_cust { 
     // This is a bit hacky as it is based upon the internal functions 
     // (though public) of the Transition class. 
     using CostType = decltype(std::declval<T>().getCost()); 
     static const bool value = std::is_base_of<Transition<CostType>, T>::value; 
    }; 
}; 

template <class TransitionCl> 
class State 
{ 
protected: 
    State() { 
     static_assert(
      detail::is_base_of_cust<TransitionCl>::value, 
      "TransitionCl class in State must be derived from Transition<Cost>" 
     ); 
    } 
public: 
    virtual void apply(const TransitionCl&) = 0; 
    virtual ~State() {} 
}; 


class StateImpl: public State<TD> 
{ 
public: 
    void apply(const TD&) override { 
     std::cout << "StateImpl::apply" << std::endl; 
    } 
}; 


int main() { 
    StateImpl impl; 
    return 0; 
} 
+0

這不允許我做'class StateImpl:public State < OpImpl > {...};'我試圖說清楚當我寫'virtual void apply(const TransitionCl&)= 0;'時,該狀態是一個抽象類。有沒有乾淨的方法? –

+2

@KyleMcCormick是的,我錯過了。我已經更新了我的答案。最終歸結爲託尼D在回答中所說的話。 – Arunmu

1

一種方法是使用getCost()返回類型(但它可能給你一個醜陋的錯誤messgae如果TransactionCl()不有這樣的公共成員功能)。

std::is_base_of< Transition< decltype(TransitionCl().getCost()) >, TransitionCl >::value, 

另一種選擇是加入typedef基類:

template < class Cost > 
class Transition { 
    public: 
    typedef Cost Cost_Type; // <------- 
    virtual Cost getCost() = 0; 
}; 

然後你就可以刪除Statetypename Cost參數和使用typedef相反在你的靜態斷言......

std::is_base_of< Transition< typename TransitionCl::Cost_Type >, TransitionCl >::value, 
相關問題