The std::tuple Class and Its Member Functions in C++
-
Use the
std::make_tuple
Function to Constructstd::tuple
Objects in C++ - Use a Function Template to Print a Tuple of Any Size in C++
This article will demonstrate multiple methods for using the std::tuple
class and its member functions in C++.
Use the std::make_tuple
Function to Construct std::tuple
Objects in C++
The function std::tuple
is the STL class template that implements a fixed-sized collection of heterogeneous types. Generally, tuples are frequently utilized in mathematics to denote the finite sequence of elements, but it’s also associated with the product of different types in programming languages.
In C++, there is a similar class, std::pair
, which can store only two heterogeneous objects. The std::tuple
object declaration usually specifies the types from which the tuple will consist of and the order in which they will be accessed. These types are specified as template parameters similar to std::pair
. The std::tuple
command can be initialized with different constructors. Still, in this case, we utilize the std::make_tuple
function. The std::make_tuple
process takes a variable number of arguments and tries to deduce the types automatically. The function returns the std::tuple
object containing the given values.
In the following example program, we implement a function named printTupleOfThree
, which prints the tuple of three values. Note that this template function cannot print the tuples with a different number of elements. The printTupleOfThree
command can be called on tuples with more than three elements, but it will only output the first three of them. So since it would be inefficient to define overloaded functions for different-sized tuples, we need to solve the problem using a different approach.
#include <iostream>
#include <tuple>
#include <vector>
using std::cout;
using std::endl;
using std::string;
using std::tuple;
using std::vector;
template <typename Tuple>
void printTupleOfThree(Tuple t) {
cout << "(" << std::get<0>(t) << ", " << std::get<1>(t) << ", "
<< std::get<2>(t) << ")" << endl;
}
int main() {
std::vector<string> v1{"one", "two", "three", "four", "five", "six"};
std::vector<int> v2 = {1, 2, 3, 4, 5, 6};
std::vector<float> v3 = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6};
auto t1 = std::make_tuple(v1[0], v1[1], v2[0]);
auto t2 = std::make_tuple(v1[0], v1[1], v2[0], v3[0], v3[1]);
printTupleOfThree(t1);
printTupleOfThree(t2);
return EXIT_SUCCESS;
}
Output:
(one, two, 1)
(one, two, 2)
Use a Function Template to Print a Tuple of Any Size in C++
The solution to the issue raised in the previous section is called variadic templates. The latter is the feature of templates to accept a variable number of arguments. Note that printTuple
is a variadic template function that calls the print
member function of the TuplePrinter
class. The latter is a class template that defines a single member function called print
, but remember that there are two definitions of the TuplePrinter
class. This implementation is called recursive template instantiation, and it’s a known technique in template-based metaprogramming.
Metaprogramming involves methods to utilize compile-time polymorphism, and it’s a far larger topic than this article can handle. It would be best if you referred to a book called C++ Templates - The Complete Guide for a detailed overview of template features and metaprogramming techniques using them. As a result, we get the printTuple
function to be compatible with different-sized tuple objects and can print all of their members to the cout
stream.
#include <iostream>
#include <tuple>
#include <vector>
using std::cout;
using std::endl;
using std::string;
using std::tuple;
using std::vector;
template <class Tuple, std::size_t N>
struct TuplePrinter {
static void print(const Tuple& t) {
TuplePrinter<Tuple, N - 1>::print(t);
std::cout << ", " << std::get<N - 1>(t);
}
};
template <class Tuple>
struct TuplePrinter<Tuple, 1> {
static void print(const Tuple& t) { std::cout << std::get<0>(t); }
};
template <class... Args>
void printTuple(const std::tuple<Args...>& t) {
std::cout << "(";
TuplePrinter<decltype(t), sizeof...(Args)>::print(t);
std::cout << ")" << endl;
}
int main() {
std::vector<string> v1{"one", "two", "three", "four", "five", "six"};
std::vector<int> v2 = {1, 2, 3, 4, 5, 6};
std::vector<float> v3 = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6};
auto t1 = std::make_tuple(v1[0], v1[1], v3[0]);
auto t2 = std::make_tuple(v1[0], v1[1], v2[1], v3[0], v3[1]);
printTuple(t1);
printTuple(t2);
return EXIT_SUCCESS;
}
Output:
(one, two, 1.1)
(one, two, 2, 1.1, 2.2)
Founder of DelftStack.com. Jinku has worked in the robotics and automotive industries for over 8 years. He sharpened his coding skills when he needed to do the automatic testing, data collection from remote servers and report creation from the endurance test. He is from an electrical/electronics engineering background but has expanded his interest to embedded electronics, embedded programming and front-/back-end programming.
LinkedIn Facebook