Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use of `std::make_pair` in std::pair : C++ STL

Tags:

c++

stl

std-pair

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?

like image 377
Sahil Arora Avatar asked Mar 01 '16 09:03

Sahil Arora


3 Answers

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}
like image 99
songyuanyao Avatar answered Nov 03 '22 00:11

songyuanyao


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

like image 43
WhiZTiM Avatar answered Nov 03 '22 01:11

WhiZTiM


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);
}
like image 39
Christian Hackl Avatar answered Nov 02 '22 23:11

Christian Hackl