2015-09-07 2 views
4

Привет У меня есть следующий код:станд :: make_pair с C++ 11

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; 
} 

Этот код всегда компилируется, но когда я добавил -std=c++0x флаг этот код не компилировать с сообщением:

[ 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 

После небольшого рытья я обнаружил, что тот факт, что этот сборник был раньше, вероятно, был ошибкой; однако, я все еще не уверен, как это исправить. Кто-нибудь имеет какие-то точки в правильном направлении?

gcc --version является gcc (Debian 4.6.3-14+rpi1) 4.6.3

+3

'make_pair' должен иметь возможность выводить типы аргументов, попробуйте удалить ваши явные аргументы шаблона:' std :: make_pair (p_pinNumber, pin) ' – melak47

+2

Сторона примечания:' if (pin) 'всегда true или не имеет эффекта если вызывается исключение –

+0

@ melak47 Это была проблема с удалением аргументов, разрешенных для компиляции кода. Спасибо! – joshu

ответ

18

std::make_pair определение изменилось между C++ 03 и C++ 11. В C++ 11 он принимает аргументы путем пересылки-ссылки, а не по значению. Это означает, что, указав свои аргументы шаблона типа явно вы в конечном итоге со следующей конкретизацией:.

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

ожидающей RValue ссылки, которые не могут связываться с lvalues, что вы проходите в

Вы не должны пройти тип шаблонные аргументы std::make_pair в явном виде, и пусть компилятор выводить их на своем собственном:

std::make_pair(p_pinNumber, pin) 
+0

Спасибо, приятно знать. У C++ 14 есть дополнительные изменения. –

+0

Спасибо за информацию! – joshu

+1

Следует подчеркнуть, что это действительно * нарушение * изменения в C++ 11. –

7

весь смысл std::make_pair заключается в упрощении создания std::pair, поэтому вам не нужно указывать аргументы шаблона, позволяя компилятору вывести их.

При вызове std::make_pair<T, U>(t, u) с явными аргументами шаблона, то вы побеждая всю цель этой функции, потому что вы предотвращение дедукции, и вы тратите время вводить дополнительные символы и потенциально создавая ненужные копии объектов, когда вам мог бы просто сделать std::pair<T, U>(t, u) (экономя себя от ввода пяти лишних, бесполезных символов).

Если вы используете std::make_pair так, как он предназначен для использования, вы даже не заметите, что он изменился на C++ 11. Если вы злоупотребляете им, бессмысленно предоставляя аргументы шаблона, то он может не работать на C++ 11, поэтому не делайте этого.

Я написал более полное объяснение в http://advogato.org/person/redi/diary/239.html

6

Заметим, что в C++ 11 станд :: make_pair часто может быть отброшен в пользу инициализатора конструктора

m_pinsInUse.insert({p_pinNumber, pin}); 
1

В дополнение к ответу @ Предоставлен NexusSquared: вы можете просто использовать новую функцию emplace std :: map:

m_pinsInUse.emplace (p_pinNumber, pin);

, который еще короче и строит std :: pair inplace вместо его построения, а затем копирует содержимое вновь созданной пары в память карты.

Смежные вопросы