Принудительное наследование класса параметров шаблона от другого шаблонного класса с частично выполненными параметрами

Итак, у меня есть следующие два класса:

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и Costклассы в его параметрах шаблона, чтобы убедиться, что его Stateкласс параметров шаблона, на самом деле, является производным от State

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 ...
};
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 & ){}
};

ADDED: Live Demo

1

По вопросам рекламы [email protected]