强制模板参数类从具有部分实现参数的另一个模板化类继承

时间:2016-01-14 05:19:33

标签: c++ templates c++11 inheritance template-inheritance

所以我有以下两个类:

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

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

但是,我希望能够将Cost模板参数放到State,因为State的功能完全独立于Cost。这样,我可以使用类似于此的语法创建非抽象类:

class TransfImpl : public Transformation< int >{
    public: int getCost(){ return 0; }
};

class StateImpl : public State< TransfImpl >{
    public:
        StateImpl(){
            static_assert(
                std::is_base_of< Transformation, TransfImpl  >::value,
                "TransfImpl must inherit from Transformation< Cost >"
            );
        }
        void apply( const TransfImpl & ){}
};

我还希望最终将此链接到第三个类,它将使用State派生类作为其模板参数,但不需要Transformation - 派生和{ {1}} - 在其模板参数中派生类,以验证其Cost派生的模板参数类实际上是否来自State

2 个答案:

答案 0 :(得分:1)

这是否符合您的需求?

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

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

class TransfImpl : public Transformation< int >{
public:
    int getCost(){ return 0; }
};

class StateImpl : public State< TransfImpl >{
public:
   StateImpl(){}
   void apply( const TransfImpl & ){}
};

已添加Live Demo

答案 1 :(得分:1)

使用

template <template <typename...> class C, typename...Ts>
std::true_type is_template_base_of_impl(const C<Ts...>*);

template <template <typename...> class C>
std::false_type is_template_base_of_impl(...);

template <template <typename...> class C, typename T>
using is_template_base_of = decltype(is_template_base_of_impl<C>(std::declval<T*>()));

你可以做

template <class TransfCl>
class State {
protected:
    static_assert(is_template_base_of<Transformation, TransfCl>::value,
                  "TransfCl class in State must be derived from Transformation<Cost>");

    // previous code ...
};