Вопрос

Я писал какой -то код, где у меня есть класс, который может принять микшины в качестве параметров переменного шаблона. Тем не менее, мне также нужно, чтобы микшины могли получить доступ к базовому классу через идиому CRTP. Вот минимальный пример, который не может сделать то, что я хочу:

template <template <class> class... Mixins>
class Foo : Mixins<Foo<Mixins...>>... {};

Однако микшин, к которому я мог бы передать Foo В целом будет несколько параметров шаблона, как так:

template <class Derived, class Type1, class Type2>
class Bar
{
    Derived& operator()()
    {
        return static_cast<Derived&>(*this);
    }
};

Как я могу изменить Foo Чтобы я мог унаследовать его от ряда базовых классов, где я управляю параметрами шаблона, принятыми каждым базовым классом? Если я вручную Foo Список параметров шаблон-образец, наряду со списком аргументов, которые для них передают, я не вижу, как я смогу связать каждый параметр шаблона с его аргументами. До сих пор я думал о чем -то подобном, но я не знаю, как я буду продолжать.

template <template <class...> class T,
    template <class...> class... Ts>
class Foo : /* How do I retrieve the arguments? */
Это было полезно?

Решение

Я не совсем уверен, что понял проблему, поэтому, пожалуйста, позвольте мне перефразировать ее, чтобы мы могли начать правую ногу.

Вам необходимо пропустить производный тип на базовые классы, в типичном варианте использования CRTP, в то же время передавая другой параметр шаблона различным базовым классам.

То есть типичный базовый класс будет:

template <typename Derived, typename X, typename Y>
struct SomeBase {
};

И вам нужно создать свой тип, чтобы вы могли управлять X а также Y и в то же время пройти полное Derived учебный класс.


Я думаю, я бы использовал apply трюк, чтобы генерировать базовый класс на лету, с адаптера, указанного в списке аргументов Derived учебный класс.

template <typename Derived, typename X, typename Y>
struct SomeBase {};

template <typename X, typename Y>
struct SomeBaseFactory {
  template <typename Derived>
  struct apply { typedef SomeBase<Derived, X, Y> type; };
};

// Generic application
template <typename Fac, typename Derived>
struct apply {
  typedef typename Fac::template apply<Derived>::type type;
};

Тогда вы создадите тип как:

typedef MyFoo< SomeBaseFactory<int, float> > SuperFoo;

Где Foo определяется как:

template <typename... Args>
struct Foo: apply<Args, Foo<Args...>>::type... {
};

И просто потому, что прошло много времени с тех пор, как я так глубоко погрузился в шаблоны, Я проверил, это сработало.


Конечно, Factory Сам сам по себе не зависит от данного типа, поэтому мы можем повторно использовать подход, который вы экспериментировали:

template <template <typename...> class M, typename... Args>
struct Factory {
  template <typename Derived>
  struct apply { typedef M<Derived, Args...> type; };
};

И да, Это тоже работает.

Другие советы

Если я правильно понимаю ваш вопрос, вы должны создать псевдонимы шаблонов, которые уменьшают каждый миксин до одного параметра шаблона.

template <typename Derived>
using BarIntFloat = Bar<Derived, Int, Float>;

template <typename Derived>
using BazQux = Baz<Derived, Qux>;

typedef Foo<BarIntFloat, BazQux> MyFoo;

Вот решение, которое я придумал. Там может быть более элегантный способ сделать это, но я не мог придумать ничего. Одно предостережение заключается в том, что все используемые микшины должны сначала быть вложенными в wrapper Структура, наряду с их соответствующими аргументами.

template <template <class...> class Mixin, class... Args>
struct wrapper
{
        typedef Mixin<Args...> type;
};

template <class... Args>
struct test
{

};

template <class Arg, class... Args>
struct test<Arg, Args...> : Arg::type, test<Args...>
{

};

template <class T>
class mixin1 {};

template <class T1, class T2>
class mixin2 {};

template <class T1, class T2, class T3>
class mixin3 {};

int main()
{
        test<wrapper<mixin1, int>, wrapper<mixin2, int, float>> foo;
        return 0;
}

@void-pointer

Это основное упущение вариальных шаблонов. Пользователь не может получить i-th-тип от T ... или получить I-три значения от значений ...

Вот ссылка от «Находной лекции 2012» Андрея Александреску:

template <typename... Ts>
void fun(const Ts&... vs) {}

• TS не является типом; VS не ценность!

typedef Ts MyList; // error!
Ts var; // error!
auto copy = vs; // error!

Таким образом, TS/VS должен быть каким -то кортежом.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top