Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

use the TYPE from the tempate type argument list

I would like to use the type information from a class template argument list.

Working example with quick workaround:

struct NoParam {};
template< typename A = NoParam,
          typename B = NoParam,
          typename C = NoParam,
          typename D = NoParam,
          typename E = NoParam,
          typename F = NoParam >
struct TypeList
{
  typedef A T1;
  typedef B T2;
  typedef C T3;
  typedef D T4;
  typedef E T5;
  typedef F T6;
};

template<typename... Types>
class Application
{
   Application()
   {
      // the actual code will store the created instances in a tuple or map..
      std::make_unique< TypeList<Types...>::T1 > ();
      std::make_unique< TypeList<Types...>::T2 > ();
      std::make_unique< TypeList<Types...>::T3 > ();
      std::make_unique< TypeList<Types...>::T4 > ();
      std::make_unique< TypeList<Types...>::T5 > ();
      std::make_unique< TypeList<Types...>::T6 > ();
   }
}

Is there any generic way...

  • to iterate over Types and get the type info (for creating instances)
  • no hard coded for only limited 6 types in the example
like image 872
rnd_nr_gen Avatar asked Oct 24 '16 09:10

rnd_nr_gen


People also ask

What is template argument list?

A template argument for a template template parameter is the name of a class template. When the compiler tries to find a template to match the template template argument, it only considers primary class templates. (A primary template is the template that is being specialized.)

What is a template type?

There are three kinds of templates: function templates, class templates and, since C++14, variable templates. Since C++11, templates may be either variadic or non-variadic; in earlier versions of C++ they are always non-variadic.

What is a template template parameter in C++?

In C++ this can be achieved using template parameters. A template parameter is a special kind of parameter that can be used to pass a type as argument: just like regular function parameters can be used to pass values to a function, template parameters allow to pass also types to a function.

What is template argument deduction in C++?

Class Template Argument Deduction (CTAD) is a C++17 Core Language feature that reduces code verbosity. C++17's Standard Library also supports CTAD, so after upgrading your toolset, you can take advantage of this new feature when using STL types like std::pair and std::vector.


1 Answers

Do not re-invent the wheel, you can use std::tuple and std::tuple_element_t for that:

template<typename... T>
using TypeList = std::tuple<T...>;

template<int I, typename T>
using Type = std::tuple_element_t<I, T>;

template<typename... Types>
class Application {
    Application() {
        std::make_unique<Type<0, TypeList<Types...>>> ();
        std::make_unique<Type<1, TypeList<Types...>>> ();
        // and so on...
    }
}

Iterate over the types is quite simple now.
It follow a minimal, working example to show you how you can do that:

#include <tuple>
#include <functional>
#include <memory>

template<typename... T>
using TypeList = std::tuple<T...>;

template<int I, typename T>
using Type = std::tuple_element_t<I, T>;

template<typename... Types>
class Application {
    using MyTypeList = TypeList<Types...>;

    template<std::size_t... I>
    void iterate(std::index_sequence<I...>) {
        // demonstration purposes, here I'm simply creating an object of the i-th type
        int _[] = { 0, (Type<I, MyTypeList>{}, 0)... };
        (void)_;
    }

public:
    void iterate() {
        iterate(std::make_index_sequence<sizeof...(Types)>{});
    }

    Application() {
        std::make_unique<Type<0, MyTypeList>> ();
        std::make_unique<Type<1, MyTypeList>> ();
        // and so on...  
    }
};

int main() {  
    Application<int, float> app;
    app.iterate();
}

Note that std::index_sequence and std::make_index_sequence are available since C++14. Anyway, you can find online several implementations to be used if you are constrained to C++11.
Otherwise, you can also iterate over the types with a couple of recursive _sfinae'd_functions that check if sizeof...(Types) has been reached.

like image 59
skypjack Avatar answered Oct 15 '22 08:10

skypjack