C++ template alias (using) in specific places
Asked Answered
A

2

7

I need to use type aliases via using (or any other method) in situations like this:

template <class T>
typename std::enable_if< /*HERE*/>::value
f (...) {};

Where I wrote HERE there are long and more than one types defined inside structures, and instead of writing typename <very long templated struct dependent on T>::type I want to write a shortcut.

And I encountered this in more situations like template specializations and suffix return type syntax. So Is there any way of using using (no pun intended) in places between the first line template <...> and the struct/class or function?.

I have tried using , (comma) something like (using X = ... , /*actually using X*/) without success.

What worked was a global scoped using

template <class Iterator>
using DT = typename DereferenceType<Iterator>::type&;

but I don't want global scope, I want the scope to be just for the template I use it. And I don't want to write DT<Iterator>, just DT.

Needless to say macros or any preprocessor directives are out of the question.


Real life example:

template <class Iterator, class GetCompValue, class SortOrder = Ascending>
typename std::enable_if<
    IsDereferenceable<Iterator>::value &&
    IsCallableLike<GetCompValue,
                   typename DereferenceType<Iterator>::type&(
                      typename DereferenceType<Iterator>::type&)>::value &&
    IsSortOrder<SortOrder>::value, void>::type
RadixSortLSDByteOffsetIter(Iterator first, Iterator last,
                           GetCompValue get_comp_value, SortOrder = kAscending) {

Here I want a shortcut for typename DereferenceType<Iterator>::type& something like:

template <class Iterator, class GetCompValue, class SortOrder = Ascending>
// using DT = typename DereferenceType<Iterator>::type&;
typename std::enable_if<
    IsDereferenceable<Iterator>::value &&
    IsCallableLike<GetCompValue, DT(DT)>::value &&
    IsSortOrder<SortOrder>::value, void>::type
RadixSortLSDByteOffsetIter(Iterator first, Iterator last,
                           GetCompValue get_comp_value, SortOrder = kAscending) {

Thank you.

Alumnus answered 27/12, 2013 at 12:22 Comment(0)
N
6

C++14 will solve your problem by introducing variable templates:

template <typename T>
T one_half = T(1) / T(2);

template <typename A, typename B>
bool is_base_of_v = std::is_base_of<A, B>::value;

Usage:

std::cout << one_half<double> << "\n" << is_base_of_v<Foo, Bar> << "\n";

So you'll be able to make your HERE into a boolean-valued variable template.


Unrelatedly, another way to clean up your traits is to get rid of the typename ...::type, like so:

template <typename C, typename T = void>
using enable_if_t = typename std::enable_if<C, T>::type;

Now you can use:

template <typename T> enable_if_t<my_condition<T>> f() { /* ... */ }
Newfangled answered 27/12, 2013 at 12:39 Comment(2)
Thank you, the clean up suggestion is very helpful. However even variable templates, if I understand correctly, need to be declared outside (globally), so there is no way for a declaration to be viewable only on the return type declaration of a function.Alumnus
@bolov: That's right, but a) those templates may be sufficiently general to make sense globally, in a library of their own, or b) you can put those into a detail:: subnamespace within your current namespace to make sure it doesn't collide with anything.Newfangled
A
0

Why don't you just alias by defining new types?

struct alias : long-long-typename {}
Accrue answered 27/12, 2013 at 12:36 Comment(1)
because of global scope. It is the same as global using. I want a shortcut to work just inside a templated function/struct, but not in the body, but in the return typeAlumnus

© 2022 - 2024 — McMap. All rights reserved.