Ваш код немного сложнее, чем нужно. Вы должны позволить std::map
делать работу, а не пытаться делать это самостоятельно. Вам нужна функция .emplace
контейнера. Он не только пропускает вставку, если в этом нет необходимости, но и дает вам право на изменение. Например, вы можете сделать что-то вроде:
#include <iostream>
#include <map>
#include <string>
int main()
{
//helper
auto print = [](auto MAP)
{
std::cout << "MAP:\n";
for (auto && each : MAP)
std::cout << each.first << "->" << each.second << '\n';
};
//work
std::map<int, std::string> MAP;
MAP.emplace(1,"").first->second = "one";
MAP.emplace(2,"").first->second = "two";
print(MAP);
MAP.emplace(1,"").first->second = "three";
print(MAP);
}
, который производит следующий вывод:
MAP:
1->one
2->two
MAP:
1->three
2->two
Конечно, это имеет странный синтаксис .first->second
, но мы можем преобразовать его в новую лямбду:
auto update = [](auto& MAP, auto index, auto entry)
{
MAP.emplace(index,"").first->second = entry;
};
, который позволяет написать следующее:
update(MAP, 1, "one");
update(MAP, 2, "two");
print(MAP);
update(MAP, 1, "three");
print(MAP);
EDIT
Поскольку вы запросили решение std::unique_ptr
, вот оно:
#include <iostream>
#include <map>
#include <string>
#include <memory>
int main()
{
//helper
auto print = [](const auto& MAP)
{
std::cout << "MAP:\n";
for (auto && each : MAP)
std::cout << each.first << "->" << *each.second.get() << '\n';
};
//work
std::map<int, std::unique_ptr<std::string>> MAP;
auto update = [](auto& MAP, auto index, auto entry)
{
*MAP.emplace(index, std::make_unique<std::string>()).first->second.get() = entry;
};
update(MAP, 1, "one");
update(MAP, 2, "two");
print(MAP);
update(MAP, 1, "three");
print(MAP);
}
К сожалению, он становится немного нечитаемым, а также раздражает, потому что std::unique_ptr
не может быть скопировано. (Это так, как это реализовано.)