C++中的元组

取自 A Tour of C++

cpp 中的元组的get<N>是一个模板函数,N必须在编译时确定,所以如果要遍历元组,就需要手写模板函数,书上提供了一种递归的写法,在引入std::apply之后,可以用apply将整个元组展开,用const auto&...接收,然后利用折叠表达式遍历每一个元素

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <iostream>
#include <tuple>

template <size_t N = 0, typename... Ts>
void print(const std::tuple<Ts...>& tup) {
if constexpr (N < sizeof...(Ts)) {
std::cout << get<N>(tup) << ' ';
print<N + 1>(tup);
}
}

template <typename... Ts>
void print_tuple_apply(const std::tuple<Ts...>& tup) {
std::apply(
[](const auto&... args) {
((std::cout << args << ' '), ...);
},
tup);
}

int main() {
std::tuple t0 {};
std::tuple t1 {"SHARK", 20, 9.99};
print_tuple_apply(t0);
print_tuple_apply(t1);
}

之前看到过通过运行时的索引变量访问元组对应元素的方法,大致来说就是编译时生成全部可能的索引,运行时的变量与之进行比较,若匹配上了就调用get<N>,其中N是编译时就确定的索引

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <variant>
#include <stdexcept>
#include <iostream>

template <std::size_t N = 0, typename... Ts>
constexpr std::variant<Ts...> tuple_index(const std::tuple<Ts...>& tpl, std::size_t i) {
if constexpr (N >= sizeof...(Ts))
throw std::out_of_range("_tuple_index out of range");
else if (i == N)
return std::variant<Ts...>{std::in_place_index<N>, std::get<N>(tpl)};
else
return tuple_index<N + 1>(tpl, i);
}

template <typename... Ts>
std::ostream& operator<<(std::ostream& s, const std::variant<Ts...>& v) {
std::visit([&](auto&& x) { s << x; }, v);
return s;
}

int main() {
std::tuple t {0, 1.11, "hello"};
int i;
std::cin >> i;
std::cout << tuple_index(t, i);
}