5

I noticed many a times that whenever one needs to assign values to a (new)std::pair, std::make_pair is used. But I did not find any use of the make_pair function, since 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;

Then what exactly is the use of this function?

Sahil Arora
  • 875
  • 2
  • 8
  • 27
  • 1
    Now try doing this with a type that doesn't have a default constructor. – milleniumbug Mar 01 '16 at 10:17
  • @milleniumbug: Valid observation, but you have the same problem with `std::make_pair`. Fundamentally, it's a design problem between language and library. You simply cannot write a heterogeneous list of object declarations initialized sequentially by an input stream. the closest you could get is to define ctors taking a stream argument, and conversion operations on the stream for the built-in types. You'd still have to repeat the stream name a lot with that style. – MSalters Mar 01 '16 at 10:27
  • Possible duplicate of [What is the purpose of std::make\_pair vs the constructor of std::pair?](https://stackoverflow.com/questions/9270563/what-is-the-purpose-of-stdmake-pair-vs-the-constructor-of-stdpair) – Jan Deinhard Nov 07 '17 at 19:27

3 Answers3

6

std::make_pair is used to create a std::pair object with the specified values.

Creates a std::pair object, deducing the target type from the types of arguments.

As a template function which supports automatic template argument type deducing, it allows you omit specifying the target template argument type. e.g.,

auto p1 = std::make_pair(1, 2);  // p1 is std::pair<int, int> with value {1, 2}
songyuanyao
  • 169,198
  • 16
  • 310
  • 405
5

There is, its advantage is called Template argument deduction. It saves a bit of typing and lets you use auto. class-template arguments must be explicitly specified, functions, mustn't.


But it becomes redundant with C++17, because we will have Template Argument Deduction For class-templates

Community
  • 1
  • 1
WhiZTiM
  • 21,207
  • 4
  • 43
  • 68
3

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:

  1. You don't always have a stream object ready. std::cin is a very special case, and std::make_pair is a very generic function.

  2. Who says that both types in the pair support operator>>?

  3. 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);
}
Christian Hackl
  • 27,051
  • 3
  • 32
  • 62