Построить массив индексов типов std :: tuple - PullRequest
2 голосов
/ 21 июня 2019

Учитывая кортеж, содержащий элементы разных типов (нет двух одинаковых):

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 Ответ

2 голосов
/ 21 июня 2019

Конечно, это выполнимо.
Давайте дадим тренировку std::integer_sequence, std::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';

Посмотреть в прямом эфире на колиру .

...