C CRTP с параметризованным базовым классом?

#c #templates #crtp

#c #шаблоны #crtp

Вопрос:

Я пытаюсь использовать CRTP с небольшим изменением. У меня есть один шаблон производного класса, и я хочу применить его к нескольким базовым классам. Но это либо невозможно, либо я просто не могу правильно использовать синтаксис. Следующий код не компилируется, но, надеюсь, иллюстрирует то, чего я хочу достичь:

 template <class Derived> struct BaseCats { /* ... */ };
template <class Derived> struct BaseDogs { /* ... */ };
// ....
template <class Derived> struct BaseN { /* ... */ };

template <template <class> class Base>
struct Wrapper 
    : 
    Base<Wrapper> // compile error - Wrapper is not a complete type
{
    Wrapper(int n) 
    { 
       // I do not want to rewrite or forward this 
       // constructor or Wrapper's operators
    }
};

typedef Wrapper<BaseCats> Cats;
typedef Wrapper<BaseDogs> Dogs;
// ...
typedef Wrapper<BaseN> MyTypeN;
 

Можно ли это сделать?

Редактировать:

Чего я пытаюсь здесь добиться?

Я переименовал часть кода выше, чтобы использовать метафору «собаки и кошки». Могут существовать такие функции, как:

 void BaseCats<Derived>::print() const 
{ 
    std::cout << (static_cast<const Derived *>this)->n << " catsn"; 
}
 

Но Wrapper будет содержать конструкторы и операторы, которые являются общими как для собак, так и для кошек. Вид инвертированного полиморфизма, при котором базовый класс имеет специализации. Причина такого решения заключается в том, что конструкторы и операторы не нужно переписывать или пересылать для каждой специализации.

Комментарии:

1. Чего вы пытаетесь достичь с помощью такого дизайна?

2. Вы понимаете, что пытаетесь сделать Base производным от Derived того, что само происходит от Base того, Что само происходит от Derived и т. Д.? Вероятно, вам следует объяснить, какова ваша цель, а не как вы ее реализуете, чтобы мы могли предложить альтернативы.

3. 1 за интересный дизайн. Не уверен, насколько это было бы полезно

Ответ №1:

Ваша ошибка компиляции может быть решена следующим образом:

 Base<Wrapper<Base> >
 

Вы забыли аргументы шаблона.

Комментарии:

1. Ах да, я действительно думал об этом, но предполагал, что мне придется писать Base<Wrapper<Base<Wrapper<Base<Wrapper<Base<Wrapper<...> > > > > > > >

2. @paperjam Этого не произойдет, пока база не наследует оболочку.