繁体   English   中英

如何将非可复制类的默认构造对象放入boost :: container :: map中?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM