Можно ли создать псевдоним шаблона?

Рассмотрим следующий код:

template< template< typename ... > class ... Ts >
struct unite
{
    template< typename ... T >
    struct type
        : Ts< T ... > ...
    { };
};

// This does not work as ::type does not name a type, but a template:

// template< template< typename ... > class ... Ts >
// using unite_t = typename unite< Ts ... >::type;

template< typename > struct debug_none {};
template< typename > struct debug_cout {};

template< typename ... > struct raise_demangled {};
template< typename ... > struct raise_specialized {};

template< typename, typename = int > struct match_default {};

template< template< typename ... > class Control >
void f()
{}

int main()
{
    f< unite< debug_none, raise_demangled, match_default >::type >();

    // Is there any way to create something like unite_t which works like this:

    // f< unite_t< debug_none, raise_demangled, match_default > >();
}

Живой пример

Вопрос: Есть ли способ создать некий "псевдоним шаблона", аналогичный псевдониму типа? (см. unite_t в приведенном выше примере)


person Daniel Frey    schedule 12.03.2015    source источник
comment
Итак, вопрос: я вспомнил, когда писал, что задавал именно этот вопрос раньше. Должен ли я закрыть свой stackoverflow.com/questions/ 17356487/ как дубликат этого? Или наоборот? :)   -  person Yakk - Adam Nevraumont    schedule 13.03.2015
comment
@Yakk Хотя ваш вопрос очень похож и относится к той же области, я не думаю, что это действительно дубликат, поскольку вы пытались избавиться от ключевого слова template в другом месте. Если решение для одной будет существовать, оно может решить и другую проблему, но похоже, что решения нет.   -  person Daniel Frey    schedule 13.03.2015


Ответы (1)


Нет, ты не можешь.

using может "вернуть" тип или переменную. Он не может «вернуть» template. Подобных механизмов нет нигде.

Вы можете сделать что-то смутно полезное, приняв соглашение, согласно которому все шаблоны являются не шаблонами, а скорее классами с псевдонимом template<?>using apply=?; внутри них (и пока мы это делаем, константы — это std::integral_constants<T,?>, а указатели — pointer_constant<T*,?>).

Сейчас все класс. template становятся просто разновидностями классов (с расширением ::apply<?...>.

Применение набора типов к такому шаблону будет выполняться с помощью:

template<class Z, class...Ts>
using apply_t = Z::template apply<Ts...>;

Итак, с «родным» шаблоном Z вы бы сделали Z<Ts...>. С этими «косвенными» шаблонами вы бы сделали apply_t<Z, Ts...>.

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

Это некрасиво.

person Yakk - Adam Nevraumont    schedule 12.03.2015
comment
Есть ли предложение исправить это? - person Brian Bi; 13.03.2015
comment
@ Брайан, я не знаю. Необходимость иметь такие псевдонимы сомнительна, так как это требуется только относительно продвинутому использованию C++, так что, возможно, никто не беспокоился. - person Yakk - Adam Nevraumont; 13.03.2015
comment
Спасибо за ваш ответ, я, вероятно, скоро отмечу его как принятый - Нет, вы не можете-часть :) К сожалению, предложенная альтернатива / обходной путь не может быть использована в моем случае, так как это сделало бы интерфейс (который виден по отношению к пользователю) еще сложнее/уродливее. Я на самом деле рассматриваю возможность отказаться от этой идеи вместо того, чтобы сбивать с толку пользователей. - person Daniel Frey; 13.03.2015