The std::tuple Class and Its Member Functions in C++

Jinku Hu Oct 12, 2023
  1. Use the std::make_tuple Function to Construct std::tuple Objects in C++
  2. Use a Function Template to Print a Tuple of Any Size in C++
The std::tuple Class and Its Member Functions 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)
Author: Jinku Hu
Jinku Hu avatar Jinku Hu avatar

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