Эквивалент использования псевдонимов для шаблонов

C++11 добавил шаблоны псевдонимов, такие как:

 template<typename T> using identity = T;
 template<bool b, typename T = void> using EnableIf = typename std::enable_if<b, T>::type;

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

По сути, вы переносите typename из места использования на псевдоним using.

Есть ли что-нибудь эквивалентное, что можно использовать для избавления от посторонних template?

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

template<typename T>
struct my_meta {
  template<typename U>
  using Template = identity<U>;
};

template<typename T>
struct my_meta {
  template<typename U>
  using Template = int;
};

который мы затем можем использовать следующим образом:

template<typename T, typename U>
typename my_meta<T>::template Template<U>
do_stuff( U&& ) { return {}; }

Это дополнительное ключевое слово template в типе возвращаемого значения существует для устранения неоднозначности возвращаемого значения моей мета-функции — это то, что я хочу устранить.

Есть ли способ указать компилятору, что результатом метавычисления является другой псевдоним или шаблон класса в C++11 или C++1y, без использования ключевого слова template в месте вызова?

Ie:

template<typename T, typename U>
my_meta_template<T><U>
do_stuff( U&& ) { return {}; }

или даже

template<template<typename> class Template>
void do_more_stuff() {}

template<typename T>
void do_stuff() {
  // syntax I want: just produce an alias or class template directly:
  do_more_stuff< my_meta_template<T> >();
  // vs what I find is required: the disambiguator:
  do_more_stuff< my_meta<T>::template Template >();
};

person Yakk - Adam Nevraumont    schedule 28.06.2013    source источник


Ответы (1)


Лучший известный мне способ удалить template — сделать простой варпер, который сделает это за вас:

template<typename Meta, typename U>
using apply = typename Meta::template Template<U>;

и везде, где вы ранее использовали template<typename> class Template, замените его на typename Meta.

template<typename Meta>
void do_more_stuff()
{
    apply<Meta, int>::func(); //=== Meta::template Template<int>::func();
}

template<typename T>
void do_stuff() {
  do_more_stuff< my_meta<T> >();
  do_more_stuff< my_meta<T> >();
};
person Yankes    schedule 28.06.2013
comment
Это хорошо для вложенных типов, но не помогает для других контекстов, таких как вызов функции-члена зависимого типа: t.template f<A>() - person Jonathan Wakely; 28.06.2013
comment
если f исправлено, то можно решить аналогичным образом: template<class U, class T, class... Args> auto call_f(T _this, Args&&... a) -> decltype(_this.template f<U>(std::forward(a)...)) { return _this.template f<U>(std::forward(a)...);} - person Yankes; 28.06.2013