diff --git a/libcxx/include/concepts b/libcxx/include/concepts --- a/libcxx/include/concepts +++ b/libcxx/include/concepts @@ -366,6 +366,14 @@ const remove_reference_t<_Up>&>> && __weakly_equality_comparable_with<_Tp, _Up>; +// [concepts.object] +template +concept movable = + is_object_v<_Tp> && + move_constructible<_Tp> && + assignable_from<_Tp&, _Tp> && + swappable<_Tp>; + // [concept.invocable] template concept invocable = requires(_Fn&& __fn, _Args&&... __args) { diff --git a/libcxx/test/std/concepts/lang/moveconstructible.h b/libcxx/test/std/concepts/lang/moveconstructible.h --- a/libcxx/test/std/concepts/lang/moveconstructible.h +++ b/libcxx/test/std/concepts/lang/moveconstructible.h @@ -5,8 +5,8 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// -#ifndef TEST_STD_CONCEPTS_LAND_MOVECONSTRUCTIBLE_H -#define TEST_STD_CONCEPTS_LAND_MOVECONSTRUCTIBLE_H +#ifndef TEST_STD_CONCEPTS_LANG_MOVECONSTRUCTIBLE_H +#define TEST_STD_CONCEPTS_LANG_MOVECONSTRUCTIBLE_H struct HasDefaultOps {}; @@ -71,4 +71,4 @@ NonMovable X; }; -#endif // TEST_STD_CONCEPTS_LAND_MOVECONSTRUCTIBLE_H +#endif // TEST_STD_CONCEPTS_LANG_MOVECONSTRUCTIBLE_H diff --git a/libcxx/test/std/concepts/lang/moveconstructible.compile.pass.cpp b/libcxx/test/std/concepts/lang/moveconstructible.compile.pass.cpp --- a/libcxx/test/std/concepts/lang/moveconstructible.compile.pass.cpp +++ b/libcxx/test/std/concepts/lang/moveconstructible.compile.pass.cpp @@ -74,4 +74,8 @@ static_assert(std::move_constructible); static_assert(std::move_constructible); +static_assert(!std::move_constructible); +static_assert(!std::move_constructible); +static_assert(!std::move_constructible); + int main(int, char**) { return 0; } diff --git a/libcxx/test/std/concepts/object/movable.h b/libcxx/test/std/concepts/object/movable.h new file mode 100644 --- /dev/null +++ b/libcxx/test/std/concepts/object/movable.h @@ -0,0 +1,162 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +#ifndef TEST_STD_CONCEPTS_OBJECT_MOVABLE_H +#define TEST_STD_CONCEPTS_OBJECT_MOVABLE_H + +struct has_const_member { + int const x; +}; + +struct has_volatile_member { + int volatile x; +}; + +struct has_cv_member { + int const volatile x; +}; + +struct has_lvalue_reference_member { + int& x; +}; + +struct has_rvalue_reference_member { + int&& x; +}; + +struct has_array_member { + int x[5]; +}; + +struct has_function_ref_member { + int (&f)(); +}; + +struct cpp03_friendly { + cpp03_friendly(cpp03_friendly const&); + cpp03_friendly& operator=(cpp03_friendly const&); +}; + +struct const_move_ctor { + const_move_ctor(const_move_ctor const&&); + const_move_ctor& operator=(const_move_ctor&&); +}; + +struct volatile_move_ctor { + volatile_move_ctor(volatile_move_ctor volatile&&); + volatile_move_ctor& operator=(volatile_move_ctor&&); +}; + +struct cv_move_ctor { + cv_move_ctor(cv_move_ctor const volatile&&); + cv_move_ctor& operator=(cv_move_ctor&&); +}; + +struct multi_param_move_ctor { + multi_param_move_ctor(multi_param_move_ctor&&, int = 0); + multi_param_move_ctor& operator=(multi_param_move_ctor&&); +}; + +struct not_quite_multi_param_move_ctor { + not_quite_multi_param_move_ctor(not_quite_multi_param_move_ctor&&, int); + not_quite_multi_param_move_ctor& operator=(not_quite_multi_param_move_ctor&&); +}; + +struct traditional_copy_assignment_only { + traditional_copy_assignment_only& + operator=(traditional_copy_assignment_only const&); +}; + +struct copy_assign_with_mutable_parameter { + copy_assign_with_mutable_parameter& + operator=(copy_assign_with_mutable_parameter&); +}; + +struct const_move_assignment { + const_move_assignment& operator=(const_move_assignment&&) const; +}; + +struct volatile_move_assignment { + const_move_assignment& operator=(const_move_assignment&&) volatile; +}; + +struct cv_move_assignment { + cv_move_assignment& operator=(cv_move_assignment&&) const volatile; +}; + +struct const_move_assign_and_traditional_move_assign { + const_move_assign_and_traditional_move_assign& + operator=(const_move_assign_and_traditional_move_assign&&); + const_move_assign_and_traditional_move_assign& + operator=(const_move_assign_and_traditional_move_assign&&) const; +}; + +struct volatile_move_assign_and_traditional_move_assign { + volatile_move_assign_and_traditional_move_assign& + operator=(volatile_move_assign_and_traditional_move_assign&&); + volatile_move_assign_and_traditional_move_assign& + operator=(volatile_move_assign_and_traditional_move_assign&&) volatile; +}; + +struct cv_move_assign_and_traditional_move_assign { + cv_move_assign_and_traditional_move_assign& + operator=(cv_move_assign_and_traditional_move_assign&&); + cv_move_assign_and_traditional_move_assign& + operator=(cv_move_assign_and_traditional_move_assign&&) const volatile; +}; + +struct const_move_assign_and_default_ops { + const_move_assign_and_default_ops(const_move_assign_and_default_ops const&) = + default; + const_move_assign_and_default_ops(const_move_assign_and_default_ops&&) = + default; + const_move_assign_and_default_ops& + operator=(const_move_assign_and_default_ops const&) = default; + const_move_assign_and_default_ops& + operator=(const_move_assign_and_default_ops&&) = default; + const_move_assign_and_default_ops& + operator=(const_move_assign_and_default_ops&&) const; +}; + +struct volatile_move_assign_and_default_ops { + volatile_move_assign_and_default_ops( + volatile_move_assign_and_default_ops const&) = default; + volatile_move_assign_and_default_ops(volatile_move_assign_and_default_ops&&) = + default; + volatile_move_assign_and_default_ops& + operator=(volatile_move_assign_and_default_ops const&) = default; + volatile_move_assign_and_default_ops& + operator=(volatile_move_assign_and_default_ops&&) = default; + volatile_move_assign_and_default_ops& + operator=(volatile_move_assign_and_default_ops&&) volatile; +}; + +struct cv_move_assign_and_default_ops { + cv_move_assign_and_default_ops(cv_move_assign_and_default_ops const&) = + default; + cv_move_assign_and_default_ops(cv_move_assign_and_default_ops&&) = default; + cv_move_assign_and_default_ops& + operator=(cv_move_assign_and_default_ops const&) = default; + cv_move_assign_and_default_ops& + operator=(cv_move_assign_and_default_ops&&) = default; + cv_move_assign_and_default_ops& + operator=(cv_move_assign_and_default_ops&&) const volatile; +}; + +struct deleted_assignment_from_const_rvalue { + deleted_assignment_from_const_rvalue( + deleted_assignment_from_const_rvalue const&); + deleted_assignment_from_const_rvalue(deleted_assignment_from_const_rvalue&&); + deleted_assignment_from_const_rvalue& + operator=(const deleted_assignment_from_const_rvalue&); + deleted_assignment_from_const_rvalue& + operator=(deleted_assignment_from_const_rvalue&&); + deleted_assignment_from_const_rvalue& + operator=(const deleted_assignment_from_const_rvalue&&) = delete; +}; + +#endif // TEST_STD_CONCEPTS_OBJECT_MOVABLE_H diff --git a/libcxx/test/std/concepts/object/movable.compile.pass.cpp b/libcxx/test/std/concepts/object/movable.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/concepts/object/movable.compile.pass.cpp @@ -0,0 +1,134 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: libcpp-no-concepts + +// template +// concept movable = see below; + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../lang/moveconstructible.h" +#include "movable.h" + +// Movable types +static_assert(std::movable); +static_assert(std::movable); +static_assert(std::movable); +static_assert(std::movable); +static_assert(std::movable); +static_assert(std::movable); +static_assert(std::movable); + +struct S {}; +static_assert(std::movable); +static_assert(std::movable); +static_assert(std::movable); +static_assert(std::movable); +static_assert(std::movable); +static_assert(std::movable); +static_assert(std::movable); +static_assert(std::movable); +static_assert(std::movable); +static_assert(std::movable); +static_assert(std::movable); +static_assert(std::movable); +static_assert(std::movable); +static_assert(std::movable); +static_assert(std::movable); +static_assert(std::movable); +static_assert(std::movable); +static_assert(std::movable); +static_assert(std::movable); +static_assert(std::movable); +static_assert(std::movable); +static_assert(std::movable); +static_assert(std::movable); +static_assert(std::movable); +static_assert(std::movable); +static_assert(std::movable); + +static_assert(std::movable >); +static_assert(std::movable >); +static_assert(std::movable >); +static_assert(std::movable > >); +static_assert(std::movable >); + +static_assert(std::movable); +static_assert(std::movable); +static_assert(std::movable); + +// Not objects +static_assert(!std::movable); +static_assert(!std::movable); +static_assert(!std::movable); +static_assert(!std::movable); +static_assert(!std::movable); +static_assert(!std::movable); +static_assert(!std::movable); +static_assert(!std::movable); +static_assert(!std::movable); +static_assert(!std::movable); +static_assert(!std::movable); + +// Core non-move assignable. +static_assert(!std::movable); +static_assert(!std::movable); + +static_assert(!std::movable); +static_assert(!std::movable); +static_assert(!std::movable); +static_assert(!std::movable); +static_assert(!std::movable); +static_assert(!std::movable); +static_assert(!std::movable); + +static_assert(std::movable); +static_assert(std::movable); +static_assert(std::movable); +static_assert(std::movable); +static_assert(std::movable); +static_assert(!std::movable); + +static_assert(!std::assignable_from); +static_assert(!std::movable); + +static_assert(!std::movable); +static_assert(std::movable); +static_assert(!std::movable); + +static_assert(!std::movable); +static_assert(!std::movable); +static_assert(!std::movable); +static_assert(std::movable); +static_assert(std::movable); +static_assert(std::movable); + +static_assert(!std::movable); +static_assert(!std::movable); +static_assert(!std::movable); +static_assert(!std::movable); +static_assert(!std::movable); + +static_assert(std::movable); + +// `move_constructible and assignable_from` implies `swappable`, +// so there's nothing to test for the case of non-swappable. + +int main(int, char**) { return 0; }