ღ.甜桃奶芙Marachino
Loading [Contrib]/a11y/accessibility-menu.js

【详解】论C++的tuple

Bro·2022-03-25 12:58·569 次阅读

【详解】论C++的tuple

Tuple详解

定义#

std::tuple<typename, ...args>

注意需要先声明头文件 include <tuple>include "tuple"

tuple 一般认为是一个不同类型元素的集合,常见用法可以用作结构体等。

基本函数#

std::get#

Copy
template<size_t __i, typename... _Elements>
constexpr __tuple_element_t<__i, tuple<_Elements...>>&
get(tuple<_Elements...>& __t) noexcept
{ return std::__get_helper<__i>(__t); }

std::get<offset>(args) 可以返回 args 的第 offset 个元素


std::make_tuple#

Copy
template<typename... _Elements>
constexpr tuple<typename __decay_and_strip<_Elements>::__type...>
make_tuple(_Elements&&... __args)
{
typedef tuple<typename __decay_and_strip<_Elements>::__type...> __result_type;
return __result_type(std::forward<_Elements>(__args)...);
}

std::make_tuple 一般表现为 std::tuple = std::make_tuple(element...)


std::tie#

Copy
template<typename... _Elements>
constexpr tuple<_Elements&...>
tie(_Elements&... __args) noexcept
{ return tuple<_Elements&...>(__args...); }

std::make_tuple 相反的,可以拆分一个 std::tuple 为一堆的常量。
如果其中有不想保留的项,可以直接用 std::ignore 代替。

Copy
signed main(int argc, char *argv[]) {
int a; char c;
std::tuple<int, double, char> t = std::make_tuple(1, 0.1, '2');
std::tie(a, std::ignore, c) = t;
std::cout << a << std::endl; // 1
std::cout << c << std::endl; // 2
return 0;
}

std::forward_as_tuple#

Copy
template<typename... _Elements>
constexpr tuple<_Elements&&...>
forward_as_tuple(_Elements&&... __args) noexcept
{ return tuple<_Elements&&...>(std::forward<_Elements(__args)...); }

用于接受右值引用数据生成 tuple, 与 std::make_tuple 不同的是它的右值是引用的,当修改其值的时候,原来赋值所用的右值也将修改,实质上就是赋予了它地址。

注意此处 tuple 内的类型应为引用,否则相当于 std::make_tuple

Copy
signed main(int argc, char *argv[]) {
int a = 0, c = 0;
float b = 0.f, d = .1;
std::tuple<int&, float&, int&, float&> tu = std::forward_as_tuple(a,b,c,d);
std::get<0> (tu) = 2;
std::get<1> (tu) = 4.5f;
std::get<2> (tu) = 234;
std::get<3> (tu) = 22.f;
std::cout << a << std::endl; // 2
std::cout << b << std::endl; // 4.5
std::cout << c << std::endl; // 234
std::cout << d << std::endl; // 22
return 0;
}

std::tuple_cat#

Copy
template<typename... _Tpls, typename = typename
enable_if<__and_<__is_tuple_like<_Tpls>...>::value>::type>
constexpr auto
tuple_cat(_Tpls&&... __tpls)
-> typename __tuple_cat_result<_Tpls...>::__type
{
typedef typename __tuple_cat_result<_Tpls...>::__type __ret;
typedef typename __make_1st_indices<_Tpls...>::__type __idx;
typedef __tuple_concater<__ret, __idx, _Tpls...> __concater;
return __concater::_S_do(std::forward<_Tpls>(__tpls)...);
}

此函数相当与 merge 之类的,可以将若干个 tuple 合并

Copy
signed main(int argc, char *argv[]) {
std::tuple<int, double> a = std::make_tuple(1, 2.5);
std::tuple<char, std::string> b = std::make_tuple('c', "F**K**F");
auto c = std::tuple_cat(a, b);
std::cout << std::get<0>(c) << std::endl; // 1
std::cout << std::get<1>(c) << std::endl; // 2.5
std::cout << std::get<2>(c) << std::endl; // c
std::cout << std::get<3>(c) << std::endl; // F**K**F
return 0;
}

std::swap#

此项不做多余解释,只是将类型相同的两个 tuple 存储的值互换

主要可以表现为

Copy
tuple1.swap(tuple2);
std::swap(tuple1, tuple2);

std::tuple_size<type>::value#

Copy
template<typename... _Elements>
struct tuple_size<tuple<_Elements...>>
: public integral_constant<size_t, sizeof...(_Elements)> { };

返回一个 tuple 的大小

Copy
signed main(int argc, char *argv[]) {
std::tuple<int, char> t = std::make_tuple(1, 'c');
std::size_t siz = std::tuple_size<decltype(t)>::value;
std::cout << siz << std::endl; // 2
}

tuple_element<I, type>::type#

Copy
template<size_t __i, typename _Head, typename... _Tail>
struct tuple_element<__i, tuple<_Head, _Tail...> >
: tuple_element<__i - 1, tuple<_Tail...> > { };

返回 tuple\(i\) 个元素的类型(注:从一个元素开始)

Copy
tuple<int, int, int, int> a(2, 3, 1, 4);
tuple_element<1, decltype(a)>::type; // int

tuple的遍历#

由于 tuple 自身的原因,无法直接遍历,而 get<num>num 必须为运行前设置好的常数

所以 tuple 的遍历需要我们手写,代码如下:

Copy
template<class Tuple, std::size_t N>
struct PrintTuple {
static void Print(const Tuple& value) {
PrintTuple<Tuple, N - 1>::Print(value);
std::cout << ' ' << std::get<N - 1>(value);
return void();
}
};
template<class Tuple>
struct PrintTuple<Tuple, 1> {
static void Print(const Tuple& value) {
std::cout << std::get<0>(value);
return void();
}
};
template<class... Args>
void TuplePrint(const std::tuple<Args...>& value) {
PrintTuple<decltype(value), sizeof ...(Args)>::Print(value);
}
posted @   xxcxu  阅读(569)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
点击右上角即可分享
微信分享提示
目录