Можно ли сделать emplace без копирования в карту при использовании агрегатной инициализации? - PullRequest
0 голосов
/ 04 марта 2019

См. Этот ответ, чтобы узнать, как вставить в без копирования значения карты.

std :: map emplace без копирования значения

Продолжая ответ, предположим, что мой тип Foo выглядит примерно так:

struct Foo {
  const int& intref_; 
  std::mutex mutex_;
}

Затем инициализируется с использованием агрегатной инициализации, подобной этой

Foo{7}

или

Foo{7, std::mutex()}

Возможно ли каким-то образом быть вставленным в карту с типом?:

std::map<size_t, Foo> mymap;

Я знаю, что мог бы просто написать конструктор для Foo - но можно ли это сделать с помощью агрегатной инициализации вместо?

Ссылка на проводник компилятора:

https://godbolt.org/z/_Fm4k1

Соответствующие ссылки на c ++:

https://en.cppreference.com/w/cpp/container/map/try_emplace

https://en.cppreference.com/w/cpp/language/aggregate_initialization

Ответы [ 2 ]

0 голосов
/ 04 марта 2019

Это не такая большая проблема с std::map::try_emplace, как с std::pair.Поскольку это простое объявление будет воспроизводить ошибку, коренящуюся в той же самой проблеме:

std::pair<const int, Foo> p(
    std::piecewise_construct,
    std::forward_as_tuple(0),
    std::forward_as_tuple(i)
);

И на самом деле это не проблема только с std::pair.Как реферат n4462 деталей, он довольно распространен.Проще говоря, эта пара c'or (как и многие библиотечные функции) выполняет пересылку следующим образом:

second(std::forward<_Args2>(std::get<_Indexes2>(__tuple2))...)

Таким образом, нет фигурных скобок и, следовательно, нет агрегированной инициализации, только инициализация значения.Ваши единственные варианты сегодня - определить фактический c'tor или использовать что-то вроде Passer By ' умное решение .

Существуетстатья в полете ( p0960 ), предназначенная для решения этой проблемы в будущих редакциях стандартов, но только время покажет, как это будет развиваться.

0 голосов
/ 04 марта 2019

Вы можете использовать приведение для косвенного построения вашей конструкции

template<typename T>
struct tag { using type = T; };

template<typename F>
struct initializer
{
    F f;
    template<typename T>
    operator T() &&
    {
        return std::forward<F>(f)(tag<T>{});
    }
};

template<typename F>
initializer(F&&) -> initializer<F>;

template<typename... Args>
auto initpack(Args&&... args)
{
    return initializer{[&](auto t) {
        using Ret = typename decltype(t)::type;
        return Ret{std::forward<Args>(args)...};
    }};
}

И использовать его как

struct Foo
{
  const int& intref_; 
  std::mutex mutex_;
};

void foo()
{
    int i = 42;
    std::map<int, Foo> m;
    m.emplace(std::piecewise_construct,
              std::forward_as_tuple(0),
              std::forward_as_tuple(initpack(i)));
}

Обратите внимание, что вы не можете продлить срок службы временного элемента, связываяэто ссылка не на стек.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...