std::tuple_cat(3)
π std::tuple_cat β the C++ Standard Library glow-up π
okay so bestie, welcome to std::tuple_cat(3) from the C++ Standard Library β yes that's the manual page name, we're being fancy today. Sit down, grab a strawberry drink π, and let me tell you about the function that literally just glues tuples together. it's giving "group chat merge" energy and honestly? iconic.
β¨ SYNOPSIS β¨
Defined in header <tuple>
template< class... Tuples >
(since C++11)
std::tuple</* CTypes */...> tuple_cat( Tuples&&... args );
(until C++14)
template< class... Tuples >
(since C++14)
constexpr std::tuple</* CTypes */...> tuple_cat( Tuples&&... args );
(until C++23)
template< tuple-like... Tuples >
(since C++23)
constexpr std::tuple</* CTypes */...> tuple_cat( Tuples&&... args );
periodt. that's the whole signature family tree. notice how she got constexpr in C++14 and then got re-constrained to tuple-like... Tuples in C++23 β main character evolution, honestly. π
πΈ DESCRIPTION πΈ
So what does she do? She constructs a tuple that is a concatenation of all tuples in args. that's it. that's the vibe. you hand her a bunch of tuples and she hands you back one big tuple. π«Ά
The element types /* CTypes */ of the returned tuple are formed by concatenating the elements type packs of all
std::tuple(until C++23)tuple-like(since C++23)
types in Tuples, in order. no cap, the order matters β first tuple's elements first, then the next, etc. π¦
β οΈ okay important caveat time, and this one's serious: the behavior is undefined if any type instd::decay_t<Tuples>...is not a specialization ofstd::tuple.
However, (until C++23) an implementation may choose to support types (such as std::array and std::pair) that follow the tuple-like protocol. so like... she might be chill about it, but don't count on it, that's implementation-dependent π
(since C++23) the types std::decay_t<Tuples>... are constrained to be tuple-like, i.e. each type therein is required to be a specialization of std::tuple or another type (such as std::array and std::pair) that models tuple-like. so from C++23 onwards this isn't vibes-based anymore, it's law. π
and one more, because detail is everything:
- If any type in
/* CTypes */is not constructible from the type of the corresponding element in the sequence of elements concatenated fromargs:- the behavior is undefined (until C++23)
- the program is ill-formed (since C++23)
like, the standard said "we're not doing undefined behaviour for this anymore, we're just gonna refuse to compile." honestly? fair. π
π§ PARAMETERS π§
argsβ zero or more tuples to concatenate. yes, zero is allowed bestie. she's flexible like that. β¨
π RETURN VALUE π
A std::tuple object composed of all elements of all argument tuples, constructed from
std::get<j>(std::forward<Ti>(arg))
for each individual element. that's the whole secret sauce right there β she's doing std::get + perfect forwarding per element and stitching them into a fresh tuple. iykyk. π
π EXAMPLE π
// Run this code
#include <iostream>
#include <string>
#include <tuple>
// helper function to print a tuple of any size
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<typename... Args, std::enable_if_t<sizeof...(Args) == 0, int> = 0>
void print(const std::tuple<Args...>& t)
{
std::cout << "()\n";
}
template<typename... Args, std::enable_if_t<sizeof...(Args) != 0, int> = 0>
void print(const std::tuple<Args...>& t)
{
std::cout << "(";
TuplePrinter<decltype(t), sizeof...(Args)>::print(t);
std::cout << ")\n";
}
// end helper function
int main()
{
std::tuple<int, std::string, float> t1(10, "Test", 3.14);
int n = 7;
auto t2 = std::tuple_cat(t1, std::make_tuple("Foo", "bar"), t1, std::tie(n));
n = 42;
print(t2);
}
btw the TuplePrinter struct recursion is genuinely such a serve, she's printing tuples of any size with templates. that's not beginner behaviour, that's icon behaviour. π₯
β OUTPUT β
(10, Test, 3.14, Foo, bar, 10, Test, 3.14, 42)
look at her!! π₯Ή and notice the last value is 42, not 7 β because std::tie(n) holds a reference to n, and n was changed to 42 before printing. the tuple was built, but the reference is still live. chef's kiss. π
π¦ SEE ALSO π¦
make_tupleβ creates a tuple object of the type defined by the argument types (C++11) (function template)tieβ creates a tuple of lvalue references or unpacks a tuple into individual objects (C++11) (function template)forward_as_tupleβ creates a tuple of forwarding references (C++11) (function template)
okay that's the page!! π big thank you to cppreference.com, version dated 2024.06.10, and to std::tuple_cat(3) for being the concatenation queen we didn't deserve. go forth and merge your tuples bestie, and remember: the behavior is undefined if you don't read the caveats. love u, bye!! π
β¨π«Ά
π¦ where this page comes from
- nixpkgs unstable: stdman 2024.07.05
- opensuse-leap 16.0: stdman 2024.07.05-bp160.1.9 Β· MIT
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms