3

考虑以下 C++03 代码(我必须使代码与 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 中进行放置。问题是,如果使用单参数构造函数,我可以完美地将构造嵌入到地图中,但我不知道如何默认构造对象,如下代码所示:

myMap.emplace(1, true); // Works
myMap.emplace(1);       // Fails

第二次调用失败,因为它被视为对 emplace(std::pair...) 重载的调用,所以似乎没有办法“default-emplace”。

有什么方法可以实现我想要的吗?

4

3 回答 3

4

通过制作A可移动但不可复制,然后将对象移动到 emplacement 函数。

在 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

}
于 2014-01-29T17:57:02.457 回答
1

出于兴趣,我玩了这个

作为一个重要的数据点,我知道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. 嗯。

然而,这激起了我的兴趣:booststd::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因此,当它使用调用时,它开始看起来像是通过内部树实现进行转发的错误。

于 2014-01-29T22:33:17.227 回答
0

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+ 编译器中工作。

于 2016-08-23T21:34:06.967 回答