Search code examples
c++c++11templatespartial-specialization

Add pointer and const to std::tuple<Types...>


I'm trying to achieve the following using the magic of C++11 templates:

Suppose I have a type like this:

using my_types = std::tuple<char, int, float>;

Having this, I'd like to get a tuple of pointers to both const and not values, i.e.:

std::tuple<char *, int *, float *, const char *, const int *, const float *>;

My solution for now:

template<typename T>
struct include_const {};

template<typename... Types>
struct include_const<std::tuple<Types...>> {
  using type = std::tuple<Types..., typename std::add_const<Types>::type...>;
};

This gives std::tuple<types, const types>. To get pointers, I can use:

template<typename T>
struct add_ptr {};

template<typename... Types>
struct add_ptr<std::tuple<Types...>> {
  using type = std::tuple<typename std::add_pointer<Types>::type...>;
};

This works, but I would like this to get a little more general: I want to have a template<trait, Types...> add_ptr that gives me pointers to both Types... and trait<Types>::type..., so the usage could be the following:

add_ptr<std::add_const, my_types> is the tuple i mentioned before add_ptr<std::add_volatile, my_types> gives std::tuple<char *, volatile char *, ...>

I would appreciate some hints on how this can be achieved. I'm not yet a template magician and would appreciate some help


Solution

  • Use a template template-parameter

    template<template<typename> class Trait, typename U>
    struct add_ptr {};
    
    template<template<typename> class Trait, typename... Types>
    struct add_ptr<Trait, std::tuple<Types...>> {
      using type = std::tuple<
                        typename std::add_pointer<Types>::type...,
                        typename std::add_pointer<
                            typename Trait<Types>::type
                        >::type...
                    >;
    };
    

    Then

    add_ptr<std::add_const, my_types>::type
    

    will be

    std::tuple<char *, int *, float *, char const *, int const *, float const *>
    

    Live demo