Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ template alias (using) in specific places

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.

like image 378
bolov Avatar asked Dec 27 '13 12:12

bolov


1 Answers

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() { /* ... */ }
like image 192
Kerrek SB Avatar answered Nov 01 '22 10:11

Kerrek SB