namespace std {
template<class T>
concept movable = is_object_v<T> &&
move_constructible<T> &&
assignable_from<T&, T> &&
swappable<T>;
}
概要
movable
は、任意の型T
がオブジェクト型かつムーブ構築・代入が可能であることを表すコンセプトである。
備考
意味論上はムーブ構築可能(move_constructible<T>
)かつムーブ代入可能(assignable_from<T&, T>
)であれば結果として必然的にswap
可能となるにもかかわらず、本コンセプト定義の制約式はswappable
コンセプトを明示的に含んでいる。
オブジェクトに対する基本操作としては「swap
可能」がもっとも原始的と考えられるため、ムーブ可能を表すコンセプトの制約式にswappable
コンセプトを含めることで、そのような「swap
可能->ムーブ可能->コピー可能」という基本操作の関係性を、コンセプトにおける包摂関係として表現している。
例
#include <iostream>
#include <concepts>
template<std::movable T>
void f(const char* name) {
std::cout << name << " is movable" << std::endl;
}
template<typename T>
void f(const char* name) {
std::cout << name << " is not movable" << std::endl;
}
struct movable {
movable(movable&&) = default;
movable& operator=(movable&&) = default;
};
struct not_movable1 {
not_movable1(not_movable1&&) = delete;
};
struct not_movable2 {
not_movable2& operator=(not_movable2&&) = delete;
};
int main() {
f<int>("int");
f<double>("double");
f<std::nullptr_t>("std::nullptr_t");
f<std::size_t>("std::size_t");
f<movable>("movable");
std::cout << "\n";
f<void>("void");
f<not_movable1>("not_movable1");
f<not_movable2>("not_movable2");
}
40
#include <iostream>
#include <concepts>
template<std::movable T>
void f(const char* name) {
std::cout << name << " is movable" << std::endl;
}
template<typename T>
void f(const char* name) {
std::cout << name << " is not movable" << std::endl;
}
struct movable {
movable(movable&&) = default;
movable& operator=(movable&&) = default;
};
出力
int is movable
double is movable
std::nullptr_t is movable
std::size_t is movable
movable is movable
void is not movable
not_movable1 is not movable
not_movable2 is not movable
バージョン
言語
- C++20
処理系
- Clang: ??
- GCC: 10.1 ✅
- Visual C++: 2019 Update 3 ✅