Частичная специализация по умолчанию для шаблона с несколькими параметрами

Есть ли способ извлечь из компилятора частичную специализацию по умолчанию?

Скажем, у меня есть этот шаблон с двумя параметрами:

template<typename A, typename B>
struct X {
    A a;
    B b;
};

и у меня также есть код, который использует шаблон с одним параметром, например:

template<template<typename> class T, typename B>
struct make_T_of_B {
    T<B> member;
};

Я хочу сказать:

make_T_of_B<X<int>, double> dummy;

где X ‹int› используется как шаблон с одним параметром. Это было бы эквивалентно этому шаблону:

template<typename B>
struct Y {
    int a;
    B b;
};

что похоже на специализацию X ‹int, B›, фактически ничего не меняя. Это похоже на специализацию по умолчанию, за исключением того, что специализация по умолчанию создает не другой шаблон, а реальный тип (другими словами, он всегда общий).

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

template<typename A>
struct Z1 {
    // start from scratch
    template<typename B>
    struct Z2 {
        A a;
        B b;
    };

    // inherit from double template above
    template<typename B>
    struct X: ::X<A, B> {}; 
};


make_T_of_B<Z1<int>::Z2, double> dummy1;
make_T_of_B<Z1<int>::X, double> dummy2;

но я считаю, что это довольно трудно читать, и я не могу четко передать мои намерения.

Спасибо.


person Rekr    schedule 11.11.2013    source источник
comment
Как насчет template <typename T> using Foo = X<int, T>;? Теперь вы можете использовать Foo<double> и получить X<int, double>.   -  person Kerrek SB    schedule 12.11.2013
comment
Да, спасибо, это то, что я искал. Это функция C ++ 11, к которой у меня нет доступа, но она отлично отвечает на вопрос. Я бы хотел принять это - если бы это был ответ ...   -  person Rekr    schedule 13.11.2013
comment
Я добавил второй ответ.   -  person Kerrek SB    schedule 13.11.2013


Ответы (2)


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

template <typename T> using Foo = X<int, T>;

Теперь Foo<double> то же самое, что X<int, double>.

Без псевдонимов в стиле C ++ 11 вы можете добиться того же с немного большим количеством шаблонов:

template <typename T> struct Foo
{
    typedef X<int, T> type;
};

Теперь вы используете Foo<double>::type.

person Kerrek SB    schedule 12.11.2013
comment
Просто очень незначительная придирка: второе предложение, хотя и вполне приемлемое в большинстве случаев, на самом деле не может работать для make_T_of_B, нет ничего, что вы могли бы использовать make_T_of_B, чтобы в конечном итоге создать X<int, double>. - person Rekr; 13.11.2013

Я бы использовал черту:

template <typename> struct applicator;

template <template <typename> class Tmpl, typename T>
struct applicator<Tmpl<T>>
{
    template <typename A>
    using rebind = make_T_of_B<Tmpl, A>;
};

Теперь вы можете сказать:

applicator<X<int>>::rebind<double> dummy;

Конечно, вы также можете переместить второй аргумент A в основной шаблон:

template <typename, typename> bpplicator;

template <template <typename> class Tmpl, typename T, typename A>
struct bpplicator<Tmpl<T>, A>
{
    using type = make_T_of_B<Tmpl, A>;  // or "typedef make_T_of_B<Tmpl, A> type;"
};

bpplicator<X<int>, double>::type dummy;

Это имеет то преимущество, что работает и в C ++ 03.

person Kerrek SB    schedule 11.11.2013
comment
Вы также можете попробовать наследование: struct bpplictor<Tmpl<T>, A> : make_t_of_B<Tmpl, A>, поэтому псевдоним using вам не понадобится. - person 0x499602D2; 12.11.2013
comment
@ 0x499602D2: Но тогда получается другой тип. С моим подходом вы буквально получаете тот же тип, как если бы вы сказали make_T_of_B<X, double>. - person Kerrek SB; 12.11.2013
comment
X (как я это написал) - это шаблон с двумя параметрами, поэтому X<int> никогда не будет успешно проанализирован, или, по крайней мере, это не для меня. Возможно, я не ясно выразился, но я хотел получить шаблон с одним параметром из шаблона с двумя параметрами, исправив его первый параметр. - person Rekr; 12.11.2013