【问题标题】:Construct an array of indices of std::tuple types构造 std::tuple 类型的索引数组
【发布时间】:2019-06-21 16:07:51
【问题描述】:

给定一个包含不同类型元素的元组(没有两个是相同的):

typedef std::tuple<bool, char, int, float, double, std::string> t1;

以及包含限制为这些类型的元素的元组类型(可以重复和省略,但不能有其他类型):

typedef std::tuple<char, int, int, double, std::string, int, double> t2;

如何为t2 中的元素构造一个std::array,其中包含t1 中匹配元素的索引?

{1, 2, 2, 4, 5, 2, 4}

【问题讨论】:

  • 如果您的最终目标是使用这些索引从 t1 中提取元素,您可以只使用std::get&lt;T&gt;(t1),其中Tt2 中的每个类型
  • @Eric 我的最终目标是用 t1 中的索引识别 t2 元素类型(现在在我的代码中 t1 是 std::variant)。并使用这个 'type_id' 我序列化和反序列化 t2 到/从二进制流。

标签: c++ tuples c++17 template-meta-programming stdtuple


【解决方案1】:

当然,这是可行的。
让我们来锻炼一下std::integer_sequencestd::tuple和相关的机械吧。

首先,编写一种方法来获取类似元组的任意类型的单个唯一匹配的索引:

template <class T, class U, std::size_t... N>
static constexpr auto tuple_index_impl(std::index_sequence<N...>) noexcept {
    static_assert((std::size_t() + ... + std::is_same_v<T, std::tuple_element_t<N, U>>) == 1,
        "There is no single exact match");
    return (0 + ... + (N * std::is_same_v<T, std::tuple_element_t<N, U>>));
}
template <class T, class U>
static constexpr std::size_t
tuple_index_v = tuple_index_impl<T, U>(std::make_index_sequence<std::tuple_size_v<U>>());

很遗憾,它已经不是标准库的一部分了。

接下来,使用它来获取所有索引并将它们放入std::array

template <class T, class U, std::size_t... N>
constexpr auto indices_impl(std::index_sequence<N...>) noexcept {
    return std::array<std::size_t, sizeof...(N)>{tuple_index_v<std::tuple_element_t<N, U>, T>...};
}
template <class T, class U>
constexpr auto indices() noexcept {
    return indices_impl<T, U>(std::make_index_sequence<std::tuple_size_v<U>>());
}

使用示例:

for (auto x : indices<t1, t2>())
    std::cout << x << '\n';

live on coliru

【讨论】:

  • 很棒的代码!但我还没弄清楚最后一个索引在哪里。您的结果是 {1, 2, 2, 4, 5, 2},但应该有 {1, 2, 2, 4, 5, 2, 4}
  • 修复了:我从错误的元组中获取了长度。
  • 你将 size_t 乘以 bool,参见 'N * std::is_same_v...'。我应该在我的代码中更改它还是保持原样?是不是 std::size_t() 比 0 好?
  • 我将它相乘是因为我想要 std::is_same 为真的唯一索引,这是获得它的最简单方法。我也在 static_assert 中使用了从 bool 到 0/1 的隐式转换。
猜你喜欢
  • 2016-11-11
  • 1970-01-01
  • 2019-06-15
  • 2011-06-20
  • 1970-01-01
  • 1970-01-01
  • 2021-10-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多