如何在C ++中迭代std :: tuple的元素

如何在C ++中迭代std :: tuple的元素

C ++元组是可以在其中存储多个类型的多个值的容器。我们可以使用 std :: get() 访问元组的元素,但是 std :: get() 始终采用常量变量参数,因此我们无法仅使用循 ​​环迭代其中。对于需要迭代元组的所有元素的任务,例如打印所有元素。

下面是一个演示迭代元组元素的程序:

// C++ program to iterate over the
// elements of an std::tuple
// using std:get()
#include <iostream>
#include <string>
#include <tuple>
 
// Driver Code
int main()
{
    // Declare a tuple and initialize
    // it using its constructor
    std::tuple<std::string, std::string,
               std::string>
        tup("Geeks", "for", "Geeks");
    std::cout << "Values of tuple: ";
 
    // std::get is used to access
    // the value of tuple.
    std::cout << std::get<0>(tup)
              << " " << std::get<1>(tup)
              << " " << std::get<2>(tup)
              << std::endl;
 
    // Make the tuple using
    // std::make_tuple function
    tup = std::make_tuple("Hey", "Welcome to",
                          "Geeksforgeeks");
 
    // Print tuple
    std::cout << "Values of tuple(Modified): ";
    std::cout << std::get<0>(tup) << " "
              << std::get<1>(tup) << " "
              << std::get<2>(tup)
              << std::endl;
 
    return 0;
}  
C++

输出:

Values of tuple: Geeks for Geeks
Values of tuple(Modified): Hey Welcome to Geeksforgeeks
C++

问题在于我们尝试迭代整个元组时会出现问题。因此,我们在这里有两种方法,迭代元组的值:

  1. 使用变参模板和元编程(不使用std :: apply)。
  2. 使用变参模板和std :: apply。

使用变参模板和模板:

变参模板用于传递打包在一个模板参数中的多个参数,并且可以在函数内部进行扩展。以下是如何浏览元组的所有元素。
下面是相同实现的实现:

// C++ program to  iterated thorough
// all values. I equals number
// of values in tuple
#include <iostream>
#include <string>
#include <tuple>
 
using namespace std;
 
// Function to iterate through all values
// I equals number of values in tuple
template <size_t I = 0, typename... Ts>
typename enable_if<I == sizeof...(Ts),
                   void>::type
printTuple(tuple<Ts...> tup)
{
    // If iterated through all values
    // of tuple, then simply return.
    return;
}
 
template <size_t I = 0, typename... Ts>
typename enable_if<(I < sizeof...(Ts)),
                   void>::type
printTuple(tuple<Ts...> tup)
{
 
    // Print element of tuple
    cout << get<I>(tup) << " ";
 
    // Go to next element
    printTuple<I + 1>(tup);
}
 
// Driver Code
int main()
{
    // Creating the tuple
    tuple<string, string, string> tup("Geeks",
                                      "for",
                                      "Geeks");
 
    // Function call
    printTuple(tup);
    return 0;
}  
C++

输出:

Geeks for Geeks
C++

使用constexpr()函数和if constexpr表达式使得此案例非常简化,但是它们只能从C++17开始使用。我也为此简化了代码,在C++17中可以运行。

下面是以上方法的实现:

//C++程序循环迭代
//所有值。我等于号码
//按元组中的值计算
#include <iostream>
#include <string>
#include <tuple>
 
using namespace std;
 
//警告:需要C++17或更高版本
template <size_t I = 0, typename... Ts>
contexpr void printTuple(tuple<Ts...> tup)
{
    //如果我们遍历了所有元素
    if constexpr (I == sizeof...(Ts))
    {
        //最后一个情况,如果没有剩余的内容
        //遍历,然后退出函数
        return;
    }
    else {
        //打印元组并转到下一个元素
        cout << get<I>(tup) << " ";
 
        //前往下一个元素。
        printTuple<I + 1>(tup);
    }
}
 
//驱动代码
int main()
{
    //初始化元组
    tuple<string,string,    string> tup("Geeks",
                                      "for",
                                      "Geeks");
   
    //函数调用
    printTuple(tup);
   
    返回0;
} 
C++

输出:

以下是上面代码的输出:

如何在C ++中迭代std :: tuple的元素

解释:

std::get() 的要求是一个常数索引,没有变量。我们总是可以为模板函数指定一个常数,这里“I”是函数的一个常数。因此,我们将有n+1个打印_num()函数的实例化,其中n是元组的大小,每个实例化都以“I”作为自身的常数。因此,这些函数的实例化将像“打印_tuple”,“打印_tuple”,…,并且“打印_tuple”一样被调用,所有这些函数将按顺序调用。这是模板元编程

注意: 因此,您无法在Geeksforgeeks IDE上运行上面的代码,您需要在另一个编译器上运行它。如果要使用C++14或C++11,则可以使用第1种方法。元组和模板仅在C++11中可用,因此无法使用较旧的版本。

使用可变模板和std::apply():

  1. 首先,简单介绍一下 std::get() 是什么。 std::get() 实现了元组元素上的某些函数,认为元组元素是该函数的值。它接受一个函数f(x,y,z…)和一个元组(x,y,z…)作为参数,并返回f返回的值。
  2. 现在还有一件事,关于可变扩展,如果我们需要对可变模板的所有值应用某个函数,那么我们就像foo(Ts)…这样做,其中Ts是我们的可变模板,而foo()是需要应用于Ts中打包的所有值的函数。这个函数“…”后面的三个点表示函数应用于可变模板的展开。
  3. Lambda函数是匿名函数,可以轻松地声明和应用。它们的实现方式如下:
[&a, b, c] (int x, float &y) {

     //函数体
}
C++
  1. 这里的x和y是函数的参数,其中x是按值传递的,y是按引用传递的。而x、y和z是在函数内部用于某些目的的变量,因此它们被传递给函数,这意味着它们将在函数的作用域内可用。
    下面是相同的实现方式:
// C++程序,遍历所有值的元组。i等于元组中值的数量。
# include <iostream>
# include <string>
# include <tuple>
 
template <typename... Ts>
void printTuple(std::tuple<Ts...> tup)
{
 
    // 获取元组大小
    std::size_t length = sizeof...(Ts);
 
    // 使用std::apply打印元素
    std::apply(
 
        // lambda表达式
        [length](auto const&... ps) {
            std::cout << "[ ";
            int k = 0;
 
            //可变展开
            ((std::cout << ps
                        << (++k == length ? "" : "; ")),
             ...);
 
            std::cout << " ]";
        },
        tuple);
}
 
//主函数
int main()
{
    // 初始化元组
    std::tuple<std::string,
               std::string, std::string>
        tup("Geeks", "for", "geeks");
 
    //函数调用
    printTuple(tup);
    return 0;
}  
C++
1. **输出:**   以下是上述代码的输出:   

如何在C ++中迭代std :: tuple的元素

注意: std::apply() 仅适用于C++17。因此,你无法在Geeksforgeeks IDE上运行此代码,你需要在另一个编译器上运行它。如果你想使用C++14或C++11,则可以使用第一种方法。元组和模板仅适用于C++11及以上版本,因此无法使用较旧版本。

Python教程

Java教程

Web教程

数据库教程

图形图像教程

大数据教程

开发工具教程

计算机教程

登录

注册