Mathieu Van Nevel
Mathieu Van Nevel

Reputation: 1486

Create a tuple with variatic type wrapped

Today I'm trying to create a tuple a little specific (for me at least) and at compile time.

I have some basic struct, let say :

struct Foo1 { int data; };
struct Foo2 { int data; };
struct Foo3 { int data; };

And another struct but with some template stuff :

template < typename T,
           size_t Size >
struct Metadata {

  using type = T;

  std::bitset<Size>  bitset;
};

So now I want to create this kind of tuple :

constexpr std::tuple<Metadata<Foo1, 3>, Metadata<Foo2, 3>, Metadata<Foo3, 3>> test { {0}, {0}, {0}};

But in an automatic way, more like:

template < typename ... Ts >
constexpr auto make_metadata() {

  return std::tuple<Metadata<Foo1, sizeof...(Ts)>, 
                    Metadata<Foo2, sizeof...(Ts)>,
                    Metadata<Foo3, sizeof...(Ts)>>{{0},{0},{0}};
}

Well the last code is far from good, so I'd like to have something like that but automatic. Maybe with tuple_cat and fold expression, but I'm a little lost. So if somebody know the answer :)

Upvotes: 4

Views: 561

Answers (3)

Barry
Barry

Reputation: 304182

You can use ... to mean multiple things in a single expression. In this case, you want to expand Ts both immediately and non-immediately:

template <class... Ts>
constexpr auto make_metadata()
{
    return std::make_tuple(Metadata<Ts, sizeof...(Ts)>{0}...);
}

Also, you don't have to write everything on a single line if it makes it clearer for you to write it this way:

template <class... Ts>
constexpr auto make_metadata()
{
    constexpr size_t N = sizeof...(Ts);
    return std::make_tuple(Metadata<Ts, N>{0}...);
}

Upvotes: 3

Jarod42
Jarod42

Reputation: 218343

The following should do what you want:

template <typename T> struct tag {};

template <typename ... Ts>
constexpr auto make_metadata() {

  return std::tuple<Metadata<Ts, sizeof...(Ts)>...>{{(tag<Ts>{}, 0)}...};
}

Upvotes: 1

Guillaume Racicot
Guillaume Racicot

Reputation: 41840

A simple variadic template expansion with std::make_tuple will suffice:

template <typename... Ts>
constexpr auto make_metadata() {
    return std::make_tuple(Metadata<Ts, sizeof...(Ts)>{0}...);
}

Upvotes: 2

Related Questions