取自 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); }
|