【问题标题】:std::make_pair with c++ 11std::make_pair 与 c++ 11
【发布时间】:2015-12-03 06:37: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

【问题讨论】:

  • make_pair 应该能够推断出参数类型,尝试删除显式模板参数:std::make_pair(p_pinNumber, pin)
  • 旁注:if (pin) 始终为真,如果抛出异常则无效
  • @melak47 这就是删除参数允许代码编译的问题。谢谢!
  • 请不要在您的代码中发布行号。将其复制并粘贴到编辑器或在线编译器表单中变得非常困难。
  • @DieterLücking 很好,感谢您指出这一点。

标签: c++ c++11 gcc boost raspberry-pi


【解决方案1】:

std::make_pair 已在 和 之间更改。

在 中,它通过转发引用而不是按值接受参数。这意味着通过显式指定其类型模板参数,您最终会得到以下实例化:

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

期望 rvalue 引用,它不能绑定到左值。

您不应明确指定 std::make_pair 的类型模板参数。相反,您应该让编译器自行推断它们:

std::make_pair(p_pinNumber, pin)

另外,由于,在使用std::map时,可以就地构造pair:

m_pinsInUse.emplace(p_pinNumber, pin);

在中,你可以利用类模板参数推导,并在不指定类模板参数的情况下构造std::pair:

std::pair(p_pinNumber, pin)

【讨论】:

  • 谢谢,很高兴知道。 C++14 定义有一个额外的变化。
  • 应该强调一点,这确实是 C++11 中的一个重大变化。
  • 实际上,这只是对滥用make_pair的愚蠢代码的重大更改
  • 因回答清晰、简洁且不显得居高临下或不必要的批评而受到赞誉。
【解决方案2】:

std::make_pair 的全部意义在于简化 std::pair 的创建,因此您无需指定模板参数,让编译器推导出它们。

如果您使用显式模板参数调用std::make_pair&lt;T, U&gt;(t, u),那么您将违背函数的全部目的,因为您正在阻止推理,并且您正在浪费时间输入额外的字符并可能创建不必要的对象的副本,而您可以只使用 std::pair&lt;T, U&gt;(t, u) 代替(避免输入五个额外的无用字符)。

如果您按照预期的方式使用std::make_pair,那么您甚至不会注意到它在 C++11 中发生了变化。如果你通过无意义地提供模板参数来滥用它,那么它可能在 C++11 中不起作用,所以不要这样做。

我在http://advogato.org/person/redi/diary/239.html写了更完整的解释

【讨论】:

    【解决方案3】:

    请注意,在 c++11 中,std::make_pair 通常可以被删除以支持初始化构造器

    m_pinsInUse.insert({p_pinNumber, pin});
    

    【讨论】:

      【解决方案4】:

      除了@NexusSquared 提供的答案: 你可以只使用 std::map 的新 emplace 函数:

      m_pinsInUse.emplace(p_pinNumber, pin);

      它甚至更短,并在原地构造 std::pair 而不是构造它,然后将新构造的对的内容复制到映射的内存中。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-06-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-10-01
        • 2014-04-26
        • 2012-03-05
        • 1970-01-01
        相关资源
        最近更新 更多