yohhoyの日記

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

C++オブジェクト基本操作:Copyable/Movable/Swappable

プログラミング言語C++のオブジェクトに対する基本操作として、コピー可能(copyable)/ムーブ可能(movable)/交換可能(swappable)の3段階が存在する。

C++における最も原始的なオブジェクト操作は交換(swap)であり、ムーブ(move)、コピー(copy)の順にオブジェクト型に対する要件が拡張される関係にある。*1

  • 交換可能(swappable):2つの変数間で「値の入れ替え」を行える。(例:無効値表現を持たないオブジェクト*2
  • ムーブ可能(movable):交換可能かつ、別の変数へ「値の移動」を行える。(例:std::unique_ptr<T>
  • コピー可能(copyable):ムーブ可能かつ、別の変数へ「値の複製」を行える。(例:std::string

注:交換操作はムーブ操作を用いても実装可能だが、常にムーブ操作を必要とするわけではない(swapメンバ関数で十分)。

この3操作の関係性は、C++標準ライブラリ提供コンセプト定義における包摂関係(subsumption relation)としても表現されている(→id:yohhoy:20190903)。C++20 18.4.9/p4, 18.6/p1より一部引用。

template<class T>
  concept swappable = requires(T& a, T& b) { ranges::swap(a, b); };
// (snip)

[Note: The semantics of the swappable and swappable_with concepts are fully defined by the ranges::swap customization point. -- end note]

This subclause describes concepts that specify the basis of the value-oriented programming style on which the library is based.

template<class T>
  concept movable =
    is_object_v<T> && move_constructible<T> &&
    assignable_from<T&, T> && swappable<T>;

template<class T>
  concept copyable =
    copy_constructible<T> && movable<T> && assignable_from<T&, T&> &&
    assignable_from<T&, const T&> && assignable_from<T&, const T>;
// (snip)

関連URL

*1:ムーブ可能だが交換不可能な型、コピー可能だがムーブ不可能な型はC++のセマンティクス上存在しえない。

*2:C++標準ライブラリでは “交換可能だがムーブ不可能な型” は提供されない。例えばムーブコンストラクタ・代入演算子をdelete宣言かつ swap 非メンバ関数のみ提供する型が該当する。https://wandbox.org/permlink/3IebVhspiFU3kgQU