Как встроенный по умолчанию объект не для копирования класса может быть вставлен в boost :: container :: map?

Рассмотрим следующий код 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. Проблема в том, что я могу безошибочно использовать emplace-construct в карту, используя конструктор с одним аргументом, но я не знаю, как создать объект по умолчанию, как показано в следующем коде:

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

Второй вызов завершается неудачно, потому что он воспринимается как вызов перегрузки emplace (std :: pair …), поэтому кажется, что нет способа «default-emplace».

Есть ли способ добиться того, чего я хочу?

3

Решение

Из интереса я играл с этим

Как важный источник данных, я знал, что std::map (в C ++ 11) поддерживает кусочная конструкция из его пар значений:

std::map<int, A> stdMap;
stdMap.emplace(std::piecewise_construct,
std::forward_as_tuple(1),
std::forward_as_tuple());

поэтому вызвал бы нужный вам конструктор. Тем не менее, так или иначе, то же самое не сразу работает для Boost’s map, Хммм.

Тем не менее, это пробудило мой интерес: повышение использует 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 вызов.

1

Другие решения

Делая 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

}
4

Добавлена ​​поддержка piecewise_construct для Boost 1.62. Итак, следующий код:

#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 +.

0
По вопросам рекламы [email protected]