Могу ли я вставить значение в вектор, который хранится на карте в C ++? - PullRequest
1 голос
/ 02 мая 2020

Мне было интересно, возможно ли вставить значение в вектор, который хранится на карте.

В настоящее время я делаю это так ...

std::map<std::string, std::vector<std::string>> my_collection;
my_collection["Key"].push_back("MyValue");

Я думал Я мог бы сделать следующее, и C ++ был бы достаточно умен, чтобы понять, что должен добавить его к вектору ... но я получаю ошибку компиляции памяти.

my_collection.emplace("Key", "MyValue");

Ответы [ 2 ]

0 голосов
/ 02 мая 2020

Независимо от того, как умный C ++ получает, он все равно должен соблюдать правила языка и интерфейсы publi c. std::map имеет члена emplace. Вы должны использовать это.

Проблема в том, что нет способа построить вектор, перемещая в него элементы (из-за того, как устроен std::initializer_list - не заводите меня)

Если вас это не волнует, и вы можете принять копирование элементов в вектор, то все, что вам нужно сделать, это:

auto test()
{
    using namespace std::string_literals;

    std::map<std::string, std::vector<std::string>> my_collection;

    my_collection.emplace("key"s, std::vector{"MyValue"s});
}

Вышеуказанное скопирует "MyValue"s в вектор, затем переместит ключ и вектор на карту.

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

Поэтому я создаю небольшую служебную функцию, которая выполняет что: создает вектор, перемещая переданные ему значения:

template <class... Args>
auto make_vector(Args&&... args)
{
    using T = std::remove_reference_t<std::common_type_t<Args...>>;
    static_assert((... && std::is_same_v<T, std::remove_reference_t<Args>>));

    auto v = std::vector<T>{};
    v.reserve(sizeof...(Args));
    (..., v.emplace_back(std::forward<Args>(args))); 

    return v;
}

auto test()
{
    using namespace std::string_literals;

    std::map<std::string, std::vector<std::string>> my_collection;

    my_collection.emplace("key", make_vector("MyValue"s));
}
0 голосов
/ 02 мая 2020

Вы можете создать вектор, вставить в него и затем переместить вектор. Таким образом, ваш объект не будет ни скопирован, ни перемещен:

std::map<std::string, std::vector<std::string>> my_collection;
std::vector<std::string> temp;
temp.emplace_back("MyValue");
my_collection["Key"] = std::move(temp);

В качестве альтернативы вы создаете вектор на карте и работаете со ссылкой:

std::map<std::string, std::vector<std::string>> my_collection;
auto &keyVec = my_collection["Key"];
keyVec.emplace_back("MyValue");

Удобно, это сводится к :

std::map<std::string, std::vector<std::string>> my_collection;
my_collection["Key"].emplace_back("MyValue");
...