What is the purpose of std::make_pair vs the constructor of std::pair?
The difference is that with std::pair
you need to specify the types of both elements, whereas std::make_pair
will create a pair with the type of the elements that are passed to it, without you needing to tell it. That's what I could gather from various docs anyways.
See this example from http://www.cplusplus.com/reference/std/utility/make_pair/
pair <int,int> one;
pair <int,int> two;
one = make_pair (10,20);
two = make_pair (10.5,'A'); // ok: implicit conversion from pair<double,char>
Aside from the implicit conversion bonus of it, if you didn't use make_pair you'd have to do
one = pair<int,int>(10,20)
every time you assigned to one, which would be annoying over time...
Use of `std::make_pair` in std::pair : C++ STL
we can directly input values to a pair, and modify them as we like.
For example:std::pair<int,int> newp;
std::cin>>newp.first>>newp.second;
newp.first = -1;
Some problems I can think of:
You don't always have a stream object ready.
std::cin
is a very special case, andstd::make_pair
is a very generic function.Who says that both types in the pair support
operator>>
?Const correctness. You may want to have a
const
pair.
Let's put these three things together to create a non-compiling example:
#include <utility>
#include <iostream>
struct Foo
{
int i;
};
struct Bar
{
double d;
};
void printPair(std::pair<Foo, Bar> const& pair)
{
std::cout << pair.first.i << " " << pair.second.d << "\n";
}
void createAndPrintPairTwice(Foo const& foo, Bar const& bar)
{
// error 1: no std::cin, need to use foo and bar
// error 2: no operator>> for Foo or Bar
// error 3: cannot change pair values after initialisation
std::pair<Foo, Bar> const newp;
std::cin >> newp.first >> newp.second;
printPair(newp);
printPair(newp);
}
int main()
{
Foo foo;
foo.i = 1;
Bar bar;
bar.d = 1.5;
createAndPrintPairTwice(foo, bar);
}
std::make_pair
solves all three problems and makes the code much nicer to read. Note that you don't have to repeat the pair's template arguments:
void createAndPrintPairTwice(Foo const& foo, Bar const& bar)
{
std::pair<Foo, Bar> const pair = std::make_pair(foo, bar);
printPair(pair);
printPair(pair);
}
What's true is that C++11 has rendered std::make_pair
much less useful than before, because you can now also write:
void createAndPrintPairTwice(Foo const& foo, Bar const& bar)
{
auto const pair = std::pair<Foo, Bar> { foo, bar };
printPair(pair);
printPair(pair);
}
What's the different between make_pair and pair?
So on from this answer, std::ref
does not work with test_vtor
as follows:
std::vector<std::pair<Callback, int>> test_vtor;
Even if you pass a reference:
test_vtor.push_back(std::make_pair(std::ref(test_map[1]), 1));
you cannot avoid your Callback
being copied.
That's the same reason that declaring std::pair<Callback&, int>
is not allowed.
Even if std::make_pair
has this exceptional rule for std::reference_wrapper
as follows:
... unless application of std::decay results in
std::reference_wrapper<X>
for some typeX
, in which case the deduced type isX&
.
There will be always a new copy of Callback
in test_vtor
(whether it's moved or copied), which will surpass its reference-ness during the construction.
Multimap insert key typeinfo with std::make_pair vs std::pair constructor
The return type of the typeid
is a std::type_info
object, which has no constructors defined. As make_pair
deduces the template arguments for its output pair from the parameters passed in, it deduces std::pair<std::type_info, int>
. It then fails to create the required pair for the above reason.
Your other line creates the pair with explicit template parameters: std::pair<std::type_index, void *>
. This time, you are creating an std::type_index
object, which does have a constructor, which takes an std::type_info
- exactly what you're giving it. So no problems.
Your make_pair
line would compile if it was also given explicit template parameters:
mm.insert(std::make_pair<std::type_index, void *>(typeid(int), 0));
Why is it better to use std::make_* instead of the constructor?
Aside from the benefit of enabling argument deduction (as already mentioned in other answers), there are also some other benefits.
std::make_pair<T1, T2>
takes care to not simply return std::pair<T1, T2>
. If you pass in a value using std::ref
, then the returned pair won't store a std::reference_wrapper
, it will store a reference.
std::make_shared
can combine allocations. shared_ptr
needs some place to hold things like the refcount, weak pointer list, etc. that cannot be stored in the shared_ptr
directly. These can be combined with the object being created, in one slightly larger block rather than in two separate blocks.
std::make_shared
and std::make_unique
both make sure that no object gets left behind if exceptions are thrown. If you call a function as f(std::shared_ptr<int>(new int), std::shared_ptr<int>(new int))
, then it's possible the compiler first allocates two int
objects, and then constructs two shared_ptr<int>
objects. If the second allocation fails, and no shared_ptr<int>
object is set up yet to release the memory on destruction, then you have a memory leak. std::make_shared
and std::make_unique
combine the allocation of int
and the construction of std::shared_ptr<int>
in a function call, and the other allocation of int
and the other construction of std::shared_ptr<int>
in another function call. Function calls cannot overlap, so if the second allocation fails, there is already a shared pointer that will be destroyed, undoing the first allocation as well.
Usefulness of std::make_pair and std::make_tuple in C++1z
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...
:
- if
Ts...
is a single object that is itself atuple
, you get a copy of it. That is,foo(std::tuple{1})
gives me atuple<int>
rather than atuple<tuple<int>>
. - if
Ts...
was a single object that is apair
, I get atuple
of those elements. That is,foo(std::pair{1, 2})
gives me atuple<int, int>
rather than atuple<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.
Difference between make_pair and curly brackets { } for assigning a pair in C++?
I tried this in an online compiler, and as far as I can see the optimized assembly for make_pair is identical to {} syntax.
https://godbolt.org/z/P7Ugkt
Why does std::make_pair return a pair of reference types
As far as I know make_pair
has the following prototype:
template<class Type1, class Type2>
std::pair<Type1,Type2> make_pair(Type1 first_value, Type2 second_value);
(Note: slightly different since C++11)
See also http://en.cppreference.com/w/cpp/utility/pair/make_pair.
This is also what the standard says in §20.3.3 [pairs.spec]
. So this must be an error in the book (or you may have overlooked something).
Constructing std::pair of integers with a variable using post-increment
From cppreference:
When calling a function (whether or not the function is inline, and whether or not explicit function call syntax is used), every value computation and side effect associated with any argument expression, or with the postfix expression designating the called function, is sequenced before execution of every expression or statement in the body of the called function.
So what is going on here is this.
int n = 0;
auto p = std::make_pair( n, n++ );
First we determine the overload of make_pair
; we get:
make_pair<int&, int>( int&, int&& )
ie, the first argument is a rvalue reference (which ends up binding to n
), the second in an lvalue reference (which ends up binding to the temporary that n++
returns).
We evaluate the arguments of make_pair
. They are sequenced in an arbitrary manner, but you'll see it doesn't matter here.
Binding n
to int&
doesn't copy a value, it just stores a reference.
Binding n++
to int&&
creates a temporary object, copies the value of n
into it, then sets up a side effect to increase n
afterwards.
When the side effect happens is the key here. As noted above, it has to happen sometime before the function make_pair
is called.
It could happen before n
is evaluated for the first argument, or after; it doesn't matter, because we are binding a reference to n
to the argument. It is, however, evaluated before we do the body of make_pair
.
So within make_pair
, it is guaranteed to have a reference to n
, whose value is 1
, and a reference to a temporary whose value is 0
. It then runs and returns a pair with those values.
It appears you misunderstood what n++
means -- it means "return the value of n
, then afterwards increase it", it does not mean "return a value 1 bigger than n
".
The way you return a value 1 bigger than n
is n+1
.
How does make_pair deduce the types implicitly?
It first creates a std::pair<double, char>
thanks to type deduction of the helper function std::make_pair
which creates a pair of exactly the same types than you passed to it, no matter to which type you later assign this pair to.
This object gets then assigned to a std::pair<int,int>
which works thanks to a templated assignment operator. This operator basically allows assignable types (U1
to T1
, U2
to T2
) which internally assigns (in your case) a double
to an int
and a char
to an int
.
The language doesn't have a feature which "forecasts" the type of variable where the expression will be used, which would be required to make a pair<int,int>
immediately without this step in between.
If you want to avoid that step you have to be explicit when constructing the pair, meaning that you shouldn't use the type deducting std::make_pair
but rather std::pair
's constructor which requires you to put the explicit types. However, I doubt this will increase performance thanks to optimization.
Related Topics
Boost::Asio Synchronous Client with Timeout
Why Does (1 << 31) >> 31 Result in -1
How to Set Given Channel of a Cv::Mat to a Given Value Efficiently Without Changing Other Channels
How to Pass a Boost Asio Tcp Socket to a Thread for Sending Heartbeat to Client or Server
How to Know the Right Max Size of Vector? Max_Size()? But No
C/C++: Casting Away Volatile Considered Harmful
What Are These Seemingly-Useless Callq Instructions in My X86 Object Files For
Array of Size Defined by Not Constant Variable
What Is the Motivation Behind Static Polymorphism in C++
Do I Get a Finished Slot If I Start Qprocess Using Startdetached
Wait for Input for a Certain Time
Passing Non-Pod Type to Variadic Function Is Undefined Behavior
Macros in the Middle of a Class or Function Declaration
How to Use Wndproc as a Class Function
When Does a Std::Vector Reallocate Its Memory Array
Programmatically Check Whether My MAChine Has Internet Access or Not