yohhoyの日記

技術的メモをしていきたい日記

std::listのsplice操作とallocator

C++標準シーケンスコンテナstd::listが提供するsplice操作では、両コンテナのアロケータが等しくなければならない。

#include <list>

std::list<int> list1 = { 1, 2, 3 };
std::list<int> list2 = { 4, 5, 6 };
std::list<int, SomeAllocator> list3 = { 42 };

list1.splice(list1.end(), list2);  // OK
list1.splice(list1.end(), list3):  // NG: 未定義動作

C++11(N3337) 23.3.5.5/p2より引用。

list provides three splice operations that destructively move elements from one list to another. The behavior of splice operations is undefined if get_allocator() != x.get_allocator().

この未定義動作(undefined behavior)はC++11から明記されている。同文面を導入した(PDF)N2525 Allocator-specific Swap and Move BehaviorよりRationale部を引用。splice操作の計算複雑度(complexity)が定数時間(constant time)であることを補強する文面とのこと。

The reason people want splice is to do an O(1) nothrow movement of nodes from one list to another. The purpose would be defeated if this guarantee did not hold. Someone wishing to copy elements between lists with unequal allocators can use the existing insert() and erase() members. Adding explicit wording here removes another barrier to eliminating the weasel words in the standard.