创建一个包含可变类型的元组

Create a tuple with variatic type wrapped

今天我试图在编译时创建一个有点具体(至少对我而言)的元组。

我有一些基本的结构,比方说:

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

还有另一个结构,但带有一些模板内容:

template < typename T,
           size_t Size >
struct Metadata {

  using type = T;

  std::bitset<Size>  bitset;
};

所以现在我想创建这种元组:

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

但以自动方式,更像是:

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}};
}

好吧,最后的代码远非如此,所以我想要类似但自动的东西。也许用 tuple_cat 和折叠表达式,但我有点迷路。所以如果有人知道答案:)

使用 std::make_tuple 的简单可变参数模板扩展就足够了:

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

下面应该做你想做的:

template <typename T> struct tag {};

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

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

您可以使用 ... 在单个表达式中表示多个事物。在这种情况下,您希望立即和非立即展开 Ts

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

此外,您不必将所有内容都写在一行中,如果这样写更清楚的话:

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