Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

std::make_pair with c++ 11

Hello I have the following code:

bool PinManager::insertPin(const std::string& p_pinNumber, const std::string& p_mode)
{
    boost::shared_ptr<GPIOPin> pin(new GPIOPin(p_pinNumber, p_mode));
    if (pin)
    {
        m_pinsInUse.insert(std::make_pair<std::string, boost::shared_ptr<GPIOPin> >(p_pinNumber, pin));
        return true;
    }
    return false;
}

This code has always compiled, but when I added the -std=c++0x flag this code fails to compile with the message:

[ 42%] Building CXX object gpioaccess/CMakeFiles/gpioaccess.dir/pinmanager/pinmanager.cpp.o
/home/pi/robot_2.0/trunk/gpioaccess/pinmanager/pinmanager.cpp: In member function 'bool gpioaccess::PinManager::insertPin(const string&, const string&)':
/home/pi/robot_2.0/trunk/gpioaccess/pinmanager/pinmanager.cpp:39:101: error: no matching function for call to 'make_pair(const string&, boost::shared_ptr<gpioaccess::GPIOPin>&)'
/home/pi/robot_2.0/trunk/gpioaccess/pinmanager/pinmanager.cpp:39:101: note: candidate is:
/usr/include/c++/4.6/bits/stl_pair.h:262:5: note: template<class _T1, class _T2> std::pair<typename std::__decay_and_strip<_T1>::__type, typename std::__decay_and_strip<_T2>::__type> std::make_pair(_T1&&, _T2&&)
gpioaccess/CMakeFiles/gpioaccess.dir/build.make:77: recipe for target 'gpioaccess/CMakeFiles/gpioaccess.dir/pinmanager/pinmanager.cpp.o' failed
make[2]: *** [gpioaccess/CMakeFiles/gpioaccess.dir/pinmanager/pinmanager.cpp.o] Error 1
CMakeFiles/Makefile2:75: recipe for target 'gpioaccess/CMakeFiles/gpioaccess.dir/all' failed
make[1]: *** [gpioaccess/CMakeFiles/gpioaccess.dir/all] Error 2
Makefile:75: recipe for target 'all' failed
make: *** [all] Error 2

After doing a little digging I found that the fact this compiled before was probably a bug; however, I am still unsure how to fix this. Does anyone have any points in the correct direction?

gcc --version is gcc (Debian 4.6.3-14+rpi1) 4.6.3

like image 503
joshu Avatar asked Sep 07 '15 16:09

joshu


People also ask

What does Make_pair do in C++?

The make_pair() function, which comes under the Standard Template Library of C++, is mainly used to construct a pair object with two elements. In other words, it is a function that creates a value pair without writing the types explicitly.

How do you initialize a pair in C++?

Another way to initialize a pair is by using the make_pair() function. g2 = make_pair(1, 'a'); Another valid syntax to declare pair is: g2 = {1, 'a'};

What is an std :: pair?

std::pair is a class template that provides a way to store two heterogeneous objects as a single unit. A pair is a specific case of a std::tuple with two elements. If neither T1 nor T2 is a possibly cv-qualified class type with non-trivial destructor, or array thereof, the destructor of pair is trivial.

Is std :: pair a container?

std::pair is not a Container. Its intention is to group two objects together. Instance of the std::pair is a class with two member objects.


2 Answers

std::make_pair has changed between c++03 and c++11.

In c++11, it accepts parameters by forwarding-references rather than by value. This means that by specifying its type template arguments explicitly you end up with the following instantiation:

std::make_pair<std::string , boost::shared_ptr<GPIOPin> >
             (std::string&&, boost::shared_ptr<GPIOPin>&&);

expecting rvalue references, which cannot bind to lvalues.

You should not specify type template arguments of std::make_pair explicitly. Instead, you should let the compiler deduce them on its own:

std::make_pair(p_pinNumber, pin)

Additionally, since c++11, when using std::map, you can construct the pair in-place:

m_pinsInUse.emplace(p_pinNumber, pin);

In c++17 you can utilize class template argument deduction, and construct std::pair without specifying class template arguments:

std::pair(p_pinNumber, pin)
like image 81
Piotr Skotnicki Avatar answered Sep 28 '22 08:09

Piotr Skotnicki


The whole point of std::make_pair is to simplify creating a std::pair so you don't need to specify the template arguments, letting the compiler deduce them.

If you call std::make_pair<T, U>(t, u) with explicit template arguments then you are defeating the entire purpose of the function, because you are preventing deduction, and you're wasting time typing extra characters and potentially creating unnecessary copies of objects, when you could just do std::pair<T, U>(t, u) instead (saving yourself from typing five extra, useless characters).

If you use std::make_pair the way it's intended to be used then you won't even notice that it changed in C++11. If you misuse it by pointlessly providing template arguments then it might not work in C++11, so don't do that.

I wrote a more complete explanation at http://advogato.org/person/redi/diary/239.html

like image 23
Jonathan Wakely Avatar answered Sep 28 '22 08:09

Jonathan Wakely