如何在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;
}
输出:
Values of tuple: Geeks for Geeks
Values of tuple(Modified): Hey Welcome to Geeksforgeeks
问题在于我们尝试迭代整个元组时会出现问题。因此,我们在这里有两种方法,迭代元组的值:
- 使用变参模板和元编程(不使用std :: apply)。
- 使用变参模板和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;
}
输出:
Geeks for Geeks
使用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;
}
输出:
以下是上面代码的输出:

解释:
std::get() 的要求是一个常数索引,没有变量。我们总是可以为模板函数指定一个常数,这里“I”是函数的一个常数。因此,我们将有n+1个打印_num()函数的实例化,其中n是元组的大小,每个实例化都以“I”作为自身的常数。因此,这些函数的实例化将像“打印_tuple”,“打印_tuple”,…,并且“打印_tuple”一样被调用,所有这些函数将按顺序调用。这是模板元编程
注意: 因此,您无法在Geeksforgeeks IDE上运行上面的代码,您需要在另一个编译器上运行它。如果要使用C++14或C++11,则可以使用第1种方法。元组和模板仅在C++11中可用,因此无法使用较旧的版本。
使用可变模板和std::apply():
- 首先,简单介绍一下 std::get() 是什么。 std::get() 实现了元组元素上的某些函数,认为元组元素是该函数的值。它接受一个函数f(x,y,z…)和一个元组(x,y,z…)作为参数,并返回f返回的值。
- 现在还有一件事,关于可变扩展,如果我们需要对可变模板的所有值应用某个函数,那么我们就像foo(Ts)…这样做,其中Ts是我们的可变模板,而foo()是需要应用于Ts中打包的所有值的函数。这个函数“…”后面的三个点表示函数应用于可变模板的展开。
- Lambda函数是匿名函数,可以轻松地声明和应用。它们的实现方式如下:
[&a, b, c] (int x, float &y) {
//函数体
}
- 这里的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;
}
1. **输出:** 以下是上述代码的输出:

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