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 is always compiled, but when I added the -std=c++0x flag, this code does not 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 a little digging, I found that the fact that this collection was previously probably a mistake; however, I'm still not sure how to fix this. Does anyone have any points in the right direction?

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

+5
source share
4 answers

The value of std::make_pair has changed between C ++ 03 and C ++ 11. In C ++ 11, it takes arguments by forwarding links, not by value. This means that by explicitly specifying its type template arguments, you get the following instance:

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

expects rvalue references that cannot communicate with the lvalues ​​you pass.

You should not explicitly pass arguments to a template like std::make_pair , and let the compiler output them yourself:

 std::make_pair(p_pinNumber, pin) 
+19
source

The whole point of std::make_pair is to simplify the creation of std::pair , so you don't need to specify template arguments, allowing the compiler to output them.

If you call std::make_pair<T, U>(t, u) with explicit template arguments, you defeat the whole purpose of the function because you prevent the subtraction, and you lose 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 entering five extra, useless characters).

If you use the std::make_pair way to use it, then you won’t even notice that it has changed to C ++ 11. If you use this template arguments incorrectly, then it may not work in C ++ 11, so do not do this.

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

+7
source

Note that in C ++ 11 std :: make_pair can often be dropped in favor of the initializer constructor

 m_pinsInUse.insert({p_pinNumber, pin}); 
+6
source

In addition to @NexusSquared: answer, you can just use the new emplace function for std :: map:

m_pinsInUse.emplace (p_pinNumber, pin);

which is even shorter and builds std :: pair inplace instead of building it, and then copies the contents of the newly created pair to the map memory.

+1
source

All Articles