類模板 std::tuple 是不同類型值的固定大小集合。 它是 std::pair 的泛化。 可以當做一個結構體使用 ,不需要創建結構體就能獲得結構體的特征
std::tuple理論上可以有無數個任意類型的成員變量,而std::pair只能是2個成員,因此在需要保存3個及以上的數據時就需要使用tuple元組了
直觀感受一下:
#include < iostream >
#include < tuple >
int main(int argc, char **argv) {
typedef std::tuple< int, double, int, double > Randy;
Randy q0(0, 1, 2, 3);
// display contents " 0 1 2 3"
std::cout < < " " < < std::get< 0 >(q0);
std::cout < < " " < < std::get< 1 >(q0);
std::cout < < " " < < std::get< 2 >(q0);
std::cout < < " " < < std::get< 3 >(q0);
std::cout < < std::endl;
Randy q1;
q1 = q0;
// display contents " 0 1 2 3"
std::cout < < " " < < std::get< 0 >(q1);
std::cout < < " " < < std::get< 1 >(q1);
std::cout < < " " < < std::get< 2 >(q1);
std::cout < < " " < < std::get< 3 >(q1);
std::cout < < std::endl;
std::tuple< char, int > q2(std::make_pair('x', 4));
// display contents " x 4"
std::cout < < " " < < std::get< 0 >(q2);
std::cout < < " " < < std::get< 1 >(q2);
std::cout < < std::endl;
Randy q3(q0);
// display contents " 0 1 2 3"
std::cout < < " " < < std::get< 0 >(q3);
std::cout < < " " < < std::get< 1 >(q3);
std::cout < < " " < < std::get< 2 >(q3);
std::cout < < " " < < std::get< 3 >(q3);
std::cout < < std::endl;
typedef std::tuple< int, float, int, float > Randy2;
Randy q4(Randy2(4, 5, 6, 7));
// display contents " 4 5 6 7"
std::cout < < " " < < std::get< 0 >(q4);
std::cout < < " " < < std::get< 1 >(q4);
std::cout < < " " < < std::get< 2 >(q4);
std::cout < < " " < < std::get< 3 >(q4);
std::cout < < std::endl;
return (0);
}
result:
0 1 2 3
0 1 2 3
x 4
0 1 2 3
4 5 6 7
成員函數及非成員函數
模板參數
Types... | -元組存儲的元素的類型。 支持空列表。 | |
---|---|---|
成員函數
(constructor) ^[1]^ (C++11) | 構造一個新的“元組”(公共成員函數) |
---|---|
operator= ^[2]^ (C++11) | 將一個“元組”的內容分配給另一個(公共成員函數) |
swap ^[3]^ (C++11) | 交換兩個元組的內容(公共成員函數) |
Non-member functions非成員函數
make_tuple ^[4]^ (C++11) | 創建由參數類型(函數模板)定義的類型的“元組”對象 |
---|---|
tie ^[5]^ (C++11) | 創建左值引用的元組或將元組解包為單個對象(函數模板) |
forward_as_tuple ^[6]^ (C++11) | 創建 forwarding references^[7]^ 的“元組”(函數模板) |
tuple_cat ^[8]^ (C++11) | 通過連接任意數量的元組(函數模板)創建一個“元組” |
std::get(std::tuple) ^[9]^ (C++11) | 元組訪問指定元素(函數模板) |
operator==operator!=operatoroperator>=operator<=> ^[10]^ (removed in C++20)(removed in C++20)(removed in C++20)(removed in C++20)(removed in C++20)(C++20) | 按字典順序比較元組中的值(函數模板) |
std::swap(std::tuple) ^[11]^ (C++11) | 特化 std::swap^[12]^ 算法(函數模板) |
輔助類
std::tuple_size ^[13]^ (C++11) | 在編譯時獲得tuple 的大小(類模板特化) |
---|---|
std::tuple_element ^[14]^ (C++11) | 獲得指定元素的類型(類模板特化) |
std::uses_allocator ^[15]^ (C++11) | 特化 std::uses_allocator^[16]^ 類型特征(類模板特化) |
std::basic_common_reference< tuple-like > ^[17]^ (C++23) | 確定“元組”和類元組類型的公共引用類型(類模板特化) |
std::common_type< tuple-like > ^[18]^ (C++23) | 確定“元組”的通用類型和類元組類型(類模板特化) |
ignore ^[19]^ (C++11) | 使用tie ^[20]^ 解壓tuple 時跳過元素的占位符(常量) |
構造函數
#include < iomanip >
#include < iostream >
#include < memory >
#include < string >
#include < tuple >
#include < type_traits >
#include < vector >
// 將向量打印到流的輔助函數
template< class Os, class T >
Os& operator< < (Os& os, std::vector< T > const& v)
{
os < < '{';
for (auto i{v.size()}; const T& e : v)
os < < e < < (--i ? "," : "");
return os < < '}';
}
template< class T >
void print_single(T const& v)
{
if constexpr (std::is_same_v< T, std::decay_t< std::string >?>)
std::cout < < std::quoted(v);
else if constexpr (std::is_same_v< std::decay_t< T >, char >)
std::cout < < "'" < < v < < "'";
else
std::cout < < v;
}
// 打印任意大小的元組的輔助函數
template< class Tuple, std::size_t N >
struct TuplePrinter {
static void print(const Tuple& t)
{
TuplePrinter< Tuple, N-1 >::print(t);
std::cout < < ", ";
print_single(std::get< N-1 >(t));
}
};
template< class Tuple >
struct TuplePrinter Tuple, 1 >{
static void print(const Tuple& t)
{
print_single(std::get< 0 >(t));
}
};
template< class... Args >
void print(const std::tuple< Args... >& t)
{
std::cout < < "(";
TuplePrinter< decltype(t), sizeof...(Args) >::print(t);
std::cout < < ")n";
}
// 輔助函數結束
int main()
{
std::tuple< int, std::string, double > t1;
std::cout < < "Value-initialized, t1: ";
print(t1);
std::tuple< int, std::string, double > t2{42, "Test", -3.14};
std::cout < < "Initialized with values, t2: ";
print(t2);
std::tuple< char, std::string, int > t3{t2};
std::cout < < "Implicitly converted, t3: ";
print(t3);
std::tuple< int, double > t4{std::make_pair(42, 3.14)};
std::cout < < "Constructed from a pair, t4: ";
print(t4);
// 給定的分配器 my_alloc 具有單參數構造函數
// my_alloc(int); 使用 my_alloc(1) 在向量中分配 5 個整數
using my_alloc = std::allocator< int >;
std::vector< int, my_alloc > v { 5, 1, my_alloc{/*1*/} };
// 使用 my_alloc(2) 在元組的向量中分配 5 個整數
std::tuple< int, std::vector< int, my_alloc >, double > t5{
std::allocator_arg, my_alloc{/*2*/}, 42, v, -3.14};
std::cout < < "Constructed with allocator, t5: ";
print(t5);
}
結果:
Value-initialized, t1: (0, "", 0)
Initialized with values, t2: (42, "Test", -3.14)
Implicitly converted, t3: ('*', "Test", -3)
Constructed from a pair, t4: (42, 3.14)
Constructed with allocator, t5: (42, {1,1,1,1,1}, -3.14)
獲取元祖元素值
#include < tuple >
#include < iostream >
#include < string >
#include < stdexcept >
std::tuple< double, char, std::string > get_student(int id)
{
switch (id)
{
case 0: return {2.13, 'A', "Randy Simpson"};
case 1: return {2.9, 'C', "Milhouse Sesame"};
case 2: return {1.22, 'D', "Kim Wiggum"};
case 3: return {0.6, 'F', "SanJie JiYuan"};
}
throw std::invalid_argument("id");
}
int main()
{
const auto student0 = get_student(0);
std::cout < < "ID: 0, "
< < "GPA: " < < std::get< 0 >(student0) < < ", "
< < "grade: " < < std::get< 1 >(student0) < < ", "
< < "name: " < < std::get< 2 >(student0) < < 'n';
const auto student1 = get_student(1);
std::cout < < "ID: 1, "
< < "GPA: " < < std::get< double >(student1) < < ", "
< < "grade: " < < std::get< char >(student1) < < ", "
< < "name: " < < std::get< std::string >(student1) < < 'n';
double gpa2;
char grade2;
std::string name2;
std::tie(gpa2, grade2, name2) = get_student(2);
std::cout < < "ID: 2, "
< < "GPA: " < < gpa2 < < ", "
< < "grade: " < < grade2 < < ", "
< < "name: " < < name2 < < 'n';
// C++17 structured binding:
const auto [ gpa3, grade3, name3 ] = get_student(3);
std::cout < < "ID: 3, "
< < "GPA: " < < gpa3 < < ", "
< < "grade: " < < grade3 < < ", "
< < "name: " < < name3 < < 'n';
}
結果:
ID: 0, GPA: 2.13, grade: A, name: Randy Simpson
ID: 1, GPA: 2.9, grade: C, name: Milhouse Sesame
ID: 2, GPA: 1.22, grade: D, name: Kim Wiggum
ID: 3, GPA: 0.6, grade: F, name: SanJie JiYuan
元素個數
std::tuple< int, char, double > randy (2, 'san_jie_ji_yuan', 0.13);
std::cout < < std::tuple_size< decltype(randy) >::value;
結果: 3
元素的類型
std::tuple< std::string, int > tq("Randy", 213);
std::tuple_element< 1, decltype(tq) >::type sesames;
sesames = std::get< 1 >(tq);
std::cout < < "sesames: " < < sesames < < std::endl;
結果:sesames: 213
評論
查看更多