Equivalent of `using` aliases for `template`s
Asked Answered
R

1

7

C++11 added alias templates such as:

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

These are much easier to use than the old template type maps that give you the return value in a ::type field because even if your type arguments are dependent on the local context, you don't need to inform the compiler that the result is a type.

In effect, you hoist the typename from the location of use to the using alias.

Is there anything equivalent that can be used to get rid of produced extraneous templates?

Suppose you had a metafunction whose output was a class or alias template instead of a type. The current method is something like this:

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;
};

which we can then use like this:

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

That extra template keyword in the return type exists to disambiguate the return value of my meta function is what I want to eliminate.

Is there any way to indicate to the compiler that the result of a metacomputation is another alias or class template in C++11 or C++1y, without using the template keyword at the location of invocation?

Ie:

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

or even

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 >();
};
Roughen answered 28/6, 2013 at 2:54 Comment(0)
P
3

Best way I know to remove template is made simple warper that will do it for you:

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

and every where you previously used template<typename> class Template replace it with 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> >();
};
Papaveraceous answered 28/6, 2013 at 12:41 Comment(2)
This is good for nested types but doesn't help for other contexts such as calling a member function of a dependent type: t.template f<A>()Sundries
if f is fixed it can be solved in similar way: 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)...);}Papaveraceous

© 2022 - 2024 — McMap. All rights reserved.