0

Is it possible (and if so, how) to generate a template pack from a indexed set of type traits so they can be used to instantiate a variant or a tuple?

#include <variant>

template<int n>
struct IntToType;

template<>
struct IntToType<0>
{
    using type = int;
    static constexpr char const* name = "int";
//  Other compile-time metadata
};

template<>
struct IntToType<1>
{
    using type = double;
    static constexpr char const* name = "double";
//  Other compile-time metadata
};

using MyVariant = std::variant<IntToType<???>::type...>;  // something with make_integer_sequence and fold expression?

Or is it necessary to use the variant as input instead:

#include <variant>

using MyVariant = std::variant<int, double>;

template<int n>
struct IntToTypeBase
{
    using type = std::variant_alternative_t<n, MyVariant>;
};

template<int >
struct IntToType;

template<>
struct IntToType<0>:IntToTypeBase<0>
{
    static constexpr char const* name = "int";
//  Other compile-time metadata
};

template<>
struct IntToType<1>:IntToTypeBase<1>
{
    static constexpr char const* name = "double";
//  Other compile-time metadata
};

or even roll your own variant, which accepts a set of traits instead of a plain list of type:

template<class IntegerType, template<auto> class Traits, size_t LastIndex>
class Variant;
user877329
  • 6,717
  • 8
  • 46
  • 88

1 Answers1

2

You could do:

#include <variant>

template<int n>
struct IntToType;

template<>
struct IntToType<0>
{
    using type = int;
    static constexpr char const* name = "int";
//  Other compile-time metadata
};

template<>
struct IntToType<1>
{
    using type = double;
    static constexpr char const* name = "double";
//  Other compile-time metadata
};

// replace NUMBER_OF_TYPES
template <typename T=std::make_index_sequence<NUMBER_OF_TYPES> >
struct make_my_variant;

template <size_t... indices>
struct make_my_variant<std::index_sequence<indices...> > {
    using type = std::variant<typename IntToType<indices>::type...>;
};

using MyVariant = typename std::make_my_variant<>::type;

Note to find the typename as a string literal, you could just use typeid(TYPE).name(). You may need to demangle this name, if you wish; you can use your compiler-specific demangler function (I think MSVC doesn't mangle type names, but on GCC you would use abi::__cxa_demangle in <cxxabi.h> header.)

Anonymous1847
  • 2,568
  • 10
  • 16
  • 1
    You need to correct some mistakes: https://gcc.godbolt.org/z/K4s788. Otherwise, a good approach. – user877329 Oct 23 '20 at 18:42
  • Now we can have some fun: https://gist.github.com/milasudril/05689532df8a6396d2b37e1a39876d5f. typeid is not constexpr (is it). And you may want some portable names if you serializing/deserializing stuff. – user877329 Oct 23 '20 at 20:02