C++23標準ライブラリのシーケンスコンテナ*1に対するRange挿入操作では、挿入先コンテナと挿入元Rangeとの要素オーバーラップが{append,prepend}_range操作でのみ許容される。それ以外のメンバ関数で要素オーバーラップしていた場合は未定義動作(undefined behavior)を引き起こす。
append_range:OKprepend_range:OKassign_range:NGinsert_range:NGinsert_range_after:NG
例示コードではstd::vectorに対して同コンテナの一部要素を逆順で末尾追加(append_range)している。*2
#include <ranges> #include <string_view> #include <vector> using namespace std::literals; // ""sv std::vector<char> vec{std::from_range, "RACE"sv}; // vec=['R', 'A', 'C', 'E'] // OK: vecの先頭3要素を逆順でvec末尾に追加 vec.append_range(vec | std::views::take(3) | std::views::reverse); // vec=['R', 'A', 'C', 'E', 'C', 'A', 'R']
C++23 24.2.4, 24.3.9.5よりシーケンスコンテナ操作の事前条件(Preconditions)を引用。
a.insert_range(p, rg)41 Preconditions:
Tis Cpp17EmplaceConstructible intoXfrom*ranges::begin(rg). Forvectorand deque,Tis also Cpp17MoveInsertable intoX, andTmeets the Cpp17MoveConstructible, Cpp17MoveAssignable, and Cpp17Swappable requirements.rgandado not overlap.
a.assign_range(rg)62 Preconditions:
Tis Cpp17EmplaceConstructible intoXfrom*ranges::begin(rg). Forvector, ifRmodels neitherranges::sized_rangenorranges::forward_range,Tis also Cpp17MoveInsertable intoX.rgandado not overlap.
a.prepend_range(rg)95 Preconditions:
Tis Cpp17EmplaceConstructible intoXfrom*ranges::begin(rg). Fordeque,Tis also Cpp17MoveInsertable intoX, andTmeets the Cpp17MoveConstructible, Cpp17MoveAssignable, and Cpp17Swappable requirements.a.append_range(rg)107 Preconditions:
Tis Cpp17EmplaceConstructible intoXfrom*ranges::begin(rg). Forvector,Tis also Cpp17MoveInsertable intoX.
template<container-compatible-range<T> R> iterator insert_range_after(const_iterator position, R&& rg);18 Preconditions:
Tis Cpp17EmplaceConstructible intoforward_listfrom*ranges::begin(rg).positionisbefore_begin()or is a dereferenceable iterator in the range [begin(),end()).rgand*thisdo not overlap.
ノート:C++標準ライブラリ文字列型std::basic_stringもassign_range, insert_range(およびappend_range, replace_with_range)操作を提供するが、要素オーバーラップに関する前提条件は存在しない。各関数の効果(Effects)によれば引数Rangeから一時オブジェクトを生成するため、要素オーバーラップしていても問題ない。
関連URL