emplace()的参数转发使构造函数参数成为const

时间:2016-04-01 04:47:18

标签: c++ c++11 boost

我正在尝试使用emplace()来构建map<K,V>条目(使用Boost)。密钥对象构造函数arg通过模板魔法正确转发,但V object构造函数arg变为const,因此它不起作用。

#include <boost/container/map.hpp>

class A {
  public:
    /**/     A( int n ) { }
    friend bool operator<( const A &a1, const A &a2 ) { return false; }
} ;

class B {
  public:
    /**/     B( const char *str ) { }
} ;

class C {
  public:
    /**/     C( B &b ) { }
} ;

int
main( int, char ** )
{
    boost::container::map<A,B>   m1;
    boost::container::map<A,C>   m2;
    B                            b( "Foo" );
    C                            c( b ); // <--- this works OK.

    m1.emplace( 1, "Hello" );
    m2.emplace( 2, b ); // <----- this fails!
}

错误是:

Error: /usr/local/include/boost/container/detail/pair.hpp:128:38: error: no matching function for call to C::C(const B&), second(::boost::forward<V>(v))

关于emplace参数转发的内容在最后一行将b转换为const b。我知道必须有一个boost::bla_bla_bla我可以申请使它运作,但我找不到它。

有人可以帮忙吗?

1 个答案:

答案 0 :(得分:1)

请注意,如果使用-std=c++11(或更高版本)进行编译,则可以使用此功能。为什么会出现这种情况需要花一点时间 - 我使用的是较早版本的boost(1.56),但我怀疑这两个版本之间的变化很大。

使用emplace通常需要完美转发。这意味着所有参数都通过std::forward<Args>(args)...转发。在下面,这依赖于引用折叠和移动语义 - 这是所有C ++ 11领域,并且在C ++ 03中没有模拟。

如果我们深入研究pair的增强代码(它实际上产生了错误),那么这就是它试图调用的构造函数:

template<class U, class V>
pair(BOOST_FWD_REF(U) u, BOOST_FWD_REF(V) v)
   : first(::boost::forward<U>(u))
   , second(::boost::forward<V>(v))
{}

不幸的是,BOOST_FWD_REF(位于move/core.hpp中)是以下之一:

#define BOOST_FWD_REF(TYPE)\
   const TYPE & \
//

#define BOOST_FWD_REF(TYPE)\
    const TYPE & \
//

当您的编译器无法识别右值引用时,它将变为const TYPE&

对此on the boost archives list进行了一些讨论。

最简单的解决方案是使用std=c++11编译。