[英]How can a default-constructed object of a non-copyable class be emplaced into a boost::container::map?
考虑下面的C ++ 03代码(我必须使代码与pre-C ++ 11编译器兼容):
// This class belongs to a third-party SDK and cannot be touched
class A {
public:
explicit A();
explicit A(bool b);
private:
// Non-copyable
A(const A&);
const A& operator= (const A&);
}
boost::container::map<int, A> myMap;
在这里使用Boost地图,因为即使在C ++ 03中它也允许放置。 问题是,如果使用单参数构造函数,我可以在地图中完成emplace-construct,但我不知道如何默认构造对象,如下代码所示:
myMap.emplace(1, true); // Works
myMap.emplace(1); // Fails
第二次调用失败,因为它被视为对emplace(std :: pair ...)重载的调用,所以似乎没有办法“default-emplace”。
有没有办法实现我想要的?
通过使A
可移动但不可复制,然后将对象移动到安置功能。
在C ++ 03中,您可以使用Boost.Move使A
可移动。 例:
#include <boost/container/map.hpp>
#include <boost/move/move.hpp>
#include <cassert>
class A {
BOOST_MOVABLE_BUT_NOT_COPYABLE(A)
public:
explicit A() {};
explicit A(bool b) {};
A(BOOST_RV_REF(A)) {}
A& operator=(BOOST_RV_REF(A)) { return * this; }
private:
// Non-copyable
// A(const A&);
// const A& operator= (const A&);
};
int main()
{
boost::container::map<int, A> myMap;
myMap.emplace(1, true); // Works
A a;
myMap.emplace(1, boost::move (a));
// myMap.emplace(1); // Fails
}
出于兴趣,我玩了这个
作为一个重要的数据点,我知道std::map
(在C ++ 11中)支持它的值对的分段构造 :
std::map<int, A> stdMap;
stdMap.emplace(std::piecewise_construct,
std::forward_as_tuple(1),
std::forward_as_tuple());
因此会调用你所追求的构造函数。 然而,不知何故,同样不会立即为Boost的map
。 嗯。
然而,这引起了我的兴趣:boost使用std::pair<const K, V>
作为值类型?!
boost::container::map<int, A>::value_type p {
std::piecewise_construct,
std::forward_as_tuple(1),
std::forward_as_tuple(true)
};
没问题。 我还可以验证此typedef 实际上是存储的类型:
static_assert(std::is_same<decltype(p), std::remove_reference<decltype(*myMap.begin())>::type>::value, "Nonstandard pair");
因此,当它使用allocator::construct
调用时,它开始看起来像是通过内部树实现转发的错误。
最近为Boost 1.62添加了piecewise_construct支持。 所以下面的代码:
#include <boost/container/map.hpp>
#include <boost/tuple/tuple.hpp>
// This class belongs to a third-party SDK and cannot be touched
class A
{
public:
explicit A(){}
explicit A(bool b);
private:
// Non-copyable
A(const A&);
const A& operator= (const A&);
};
int main()
{
using namespace boost::container;
map<int, A> myMap;
myMap.emplace(piecewise_construct, boost::tuple<int>(1), boost::tuple<>());
return 0;
}
应该在C ++ 03和C ++ 11 +编译器中工作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.