In my understanding, the sole reason for the existence of std::make_pair
and std::make_tuple
is that you don't have to write the types by yourself as they are automatically deduced. In C++1z, we have template argument deduction for class templates, which allows us to simply write
std::pair p(1, 2.5); // C++1z
instead of
auto p = std::make_pair(1, 2.5); // C++11/14
The situation for std::tuple
is analogous. This leads to the following question: In C++1z, is there a situation in which it is beneficial to use std::make_pair
and std::make_tuple
instead of using the constructors of std::pair
and std::tuple
?
Please, consider just pure C++1z code (i.e. no need for backward compatibility with C++14) and assume that everyone is familiar with this C++1z feature.
std::make_tupleCreates a tuple object, deducing the target type from the types of arguments. For each Ti in Types... , the corresponding type Vi in VTypes... is std::decay<Ti>::type unless application of std::decay results in std::reference_wrapper<X> for some type X , in which case the deduced type is X& .
make_tuple() :- make_tuple() is used to assign tuple with values. The values passed should be in order with the values declared in tuple. // C++ code to demonstrate tuple, get() and make_pair() #include<iostream> #include<tuple> // for tuple.
In C++1z, is there a situation in which it is beneficial to use
std::make_pair
andstd::make_tuple
instead of using the constructors ofstd::pair
andstd::tuple
?
There are always fun exceptions to every rule. What do you want to happen to std::reference_wrapper
?
int i = 42; auto r = std::ref(i); pair p(i, r); // std::pair<int, std::reference_wrapper<int> > auto q = std::make_pair(i,r); // std::pair<int, int&>
If you want the latter, std::make_pair
is what you want.
Another situation cames in generic code. Let's say I have a template parameter pack that I want to turn into a tuple, would I write this?
template <typename... Ts> auto foo(Ts... ts) { return std::tuple(ts...); }
Now the intent of that code is to probably to get a std::tuple<Ts...>
out of it, but that's not necessarily what happens. It depends on Ts...
:
Ts...
is a single object that is itself a tuple
, you get a copy of it. That is, foo(std::tuple{1})
gives me a tuple<int>
rather than a tuple<tuple<int>>
.Ts...
was a single object that is a pair
, I get a tuple
of those elements. That is, foo(std::pair{1, 2})
gives me a tuple<int, int>
rather than a tuple<pair<int, int>>
.In generic code, I would stay away from using CTAD for types like tuple
because it's never clear what you're going to get. make_tuple
doesn't have this problem. make_tuple(tuple{1})
is a tuple<tuple<int>>
and make_tuple(pair{1, 2})
is a tuple<pair<int, int>>
because that's what you asked for.
Additionally, since std::make_pair
is a function template, you can pass that into another function template that maybe wants to do something:
foo(std::make_pair<int, int>);
This doesn't seem super useful, but somebody somewhere is using it to solve a problem - and you can't just pass std::pair
there.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With