Перенос элементов между ассоциативными контейнерами



Пост для тех, кто много работает с древовидными структурами данных. Таких среди нас, думаю, немного. Но мне кажется фишка интересная. Слышали когда-нибудь об одной изящной функции, представленной в C++17, которая значительно облегчила нам жизнь при работе с ассоциативными контейнерами? Я говорю о методе extract, который как бы вырезает ноду из внутренней структуры контейнера и помещает его наружу, в специальный хэндлер node_type, не дергая конструкторы класса.



Что было до С++17



В эпоху до C++17 перемещение или перенос узлов между ассоциативными контейнерами было обременительной задачей. Представьте, что у вас есть узел в одном std::map или std::set, и вы хотите переместить его в другой контейнер. Вам приходилось вручную выполнять операцию копирования/перемещения объекта во временный объект, удаления этой ноды из одной мапы и вставки в другую копированием/перемещением . Это было не очень красиво эстетически, нельзя было трансферрить объекты, у которых не было конструкторов копирования и перемещения. Ну и конечно были совершенно лишние вызовы конструкторов.



Splicing в C++17



С появлением C++17 нам была предоставлена возможность для так называемого «сращивания». Вот как это работает:



👉🏿std::map::extract() и std::set::extract()



Эти новые функции-члены позволяют вам извлекать узел из std::map или std::set и возвращать его как «извлеченный» узел типа node_type. Эта операция эффективно отвязывает узел от исходного контейнера и внутри этого узла объект остаётся нетронутым. Никаких вызовов конструкторов объекта!



👉🏿std::map::insert() и std::set::insert()



Имея извлеченный узел на руках, вы теперь можете легко вставить его в другой std::map или std::set, используя метод insert(). Перенесенный узел будет легко интегрирован в новый контейнер без необходимости вовлечения конструкторов.



И все! Такой приём можно провернуть с любыми видами упорядоченных и неупорядоченных ассоциативных контейнеров. И да, это все ещё может вызывать перебалансировку дерева. Куда же без этого.



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



Короче говоря, C++17 в целом значительно облегчил нам жизнь. Эта фича не геймченджер, но очень приятное нововведение, которое позитивно сказалось на качестве кода и его производительности.



Stay updated. Stay cool.



#cpp17 #datastructures #STL