Reputation: 1486
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
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
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
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