Template()的参数转发使构造函数参数变为常量
Argument forwarding for emplace() makes constructor arguments const
我正在尝试使用emplace()
来就地构造map<K,V>
条目(使用Boost)。关键对象构造函数arg通过模板magic正确转发,但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))
在最后一行中,关于模板参数转发的某些内容将b
转换为const b
。我知道一定有一个boost::bla_bla_bla
我可以申请它,但我一直没能找到它。
有人能帮忙吗?
请注意,如果您使用-std=c++11
(或更高版本)编译它,这将起作用。为什么会出现这种情况需要一点挖掘——我使用的是稍旧版本的boost(1.56),但我怀疑这在两个版本之间是否有太大变化。
使用emplace
通常需要完美的转发。这意味着所有参数都是通过std::forward<Args>(args)...
转发的。在底层,这依赖于引用折叠和移动语义——这都是C++11的领域,在C++03中没有类似的东西。
如果我们深入研究pair
的boost代码(它实际上正在生成错误),那么这就是它试图调用的构造函数:
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&
。
boost档案列表中对此有一些讨论。
最简单的解决方案是简单地使用std=c++11
进行编译。
相关文章:
- C++:使用运算符 = 调用多参数构造函数
- 通过零参数构造函数创建的 glm::mat4 应该包含哪些值?
- 好奇的混合与可变参数构造函数
- 具有默认值的单个参数构造函数是否与默认构造函数相同?
- 为什么我们需要创建一个单参数构造函数来使用临时的无名称对象
- 在可变参数构造函数中初始化常量数组
- C++ 显式多参数构造函数歧义
- 零一参数构造函数
- 可变参数构造函数中的 SFINAE
- 当没有显式关键字与单参数构造函数一起使用时,编译器可以发出警告
- 可变参数类模板和可变参数构造函数
- 确保模板参数类型与其可变参数构造函数的类型匹配
- C++默认参数构造函数与内联初始化优先级
- 如何在 c++ 中将包含复制构造函数的类的参数构造函数称为私有?
- 自动存储中没有无参数构造函数的类对象和异常
- 警告:用两个参数构造函数返回对象时,表达结果未使用
- 如何在C++中调用无参数构造函数
- 在 c++ 中具有多个参数构造函数的模板类存在问题
- 可变参数构造函数优先于用户提供的移动构造函数,除非默认
- 如何从可变参数构造函数参数构造任何对象?