C++成员函数及非成员函数详解

嵌入式技术

1378人已加入

描述

类模板 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

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分