Array of types?

Viewed 943

I have several structs, and I want to create an array of them so that I can use its members as an argument for a template, something like types = {int, float}; multiply<types[i]>();. It can be done through overloading, but I have lots of functions so this is not a way. As far as I know, we can store types only as pointers (so I'll actually have to dereference it: multiply<*types[i]>();), but here I stop to understand because to create a pointer I have to know type of variable it's pointing to, and what is a type of a class (of a type)? I thought "screw it, I'll use auto", but then it seems to be that pointers to different classes are of different types, so that I have to erase their type to store them in a common array, and so on, I have this now:

auto types = {std::make_shared<void>(Student), std::make_shared<void>(Citizen)};

And it says that Student and Citizen don't refer to a value.

2 Answers

The convenient built-in array of types in C++ is std::tuple<Types...>.

To access the ith type in a std::tuple, use std::tuple_element_t<i, your_tuple>.

For example:

using types = std::tuple<int, float>;
multiply<std::tuple_element_t<i, types>>();

Types are only "there" at compile time, thus all of your indices need to be at compile time, and you store them in the type information (here the variadic type in std::tuple), instead of in a variable.

You can use a helper type to make this less verbose:

template<class... Types>
struct type_array {
    using as_tuple = std::tuple<Types...>;

    template<std::size_t I>
    using get = std::tuple_element_t<I, as_tuple>;

    static constexpr std::size_t size = sizeof...(Types);
};

using types = type_array<int, float>;
multiply<types::get<i>>();

I have several structs, and I want to create an array of them

In C++, arrays contain elements all of the same type. At runtime, types have disappeared since they have been erased (except with RTTI, related to dynamic_cast). So you cannot directly have an array containing elements of different types (or don't call that an array).

Please refer to this site and later to the C++11 standard n3337 for more about C++. You could find the C++17 standard too.

It looks that you want some tagged union in C++. Consider then using the standard std::variant template from C++17.

If you want a product type, use of course std::tuple as answered by Artyer

Take advantage of existing C++ containers, when they fit your needs. Of course you can combine them with product types, sum types, strings, nested containers, smart pointers, etc...

If you cannot use C++17 but just C++11 and need to implement some tagged union, use some anonymous union but be aware of the rule of five. Consider also using Boost or Qt (both provide tagged unions in their own way).

Read also a good C++ programming book, since C++ is a very difficult programming language (that I don't claim to master, just to use).

Related