构造std :: tuple类型的索引数组

时间:2019-06-21 16:07:51

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

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

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

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

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

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

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

1 个答案:

答案 0 :(得分:2)

当然可以。
让我们给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看到它。