diff --git a/libcxx/include/concepts b/libcxx/include/concepts --- a/libcxx/include/concepts +++ b/libcxx/include/concepts @@ -374,6 +374,14 @@ assignable_from<_Tp&, _Tp> && swappable<_Tp>; +template +concept copyable = + copy_constructible<_Tp> && + movable<_Tp> && + assignable_from<_Tp&, _Tp&> && + assignable_from<_Tp&, const _Tp&> && + assignable_from<_Tp&, const _Tp>; + // [concept.invocable] template concept invocable = requires(_Fn&& __fn, _Args&&... __args) { diff --git a/libcxx/test/std/concepts/object/copyable.h b/libcxx/test/std/concepts/object/copyable.h new file mode 100644 --- /dev/null +++ b/libcxx/test/std/concepts/object/copyable.h @@ -0,0 +1,65 @@ +//===----------------------------------------------------------------------===// +// +// 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_COPYABLE_H +#define TEST_STD_CONCEPTS_OBJECT_COPYABLE_H + +#include + +#include "movable.h" + +struct no_copy_constructor { + no_copy_constructor(no_copy_constructor const&) = delete; + no_copy_constructor(no_copy_constructor&&) = default; +}; + +struct no_copy_assignment { + no_copy_assignment& operator=(no_copy_assignment const&) = delete; + no_copy_assignment& operator=(no_copy_assignment&&) = default; +}; + +struct no_copy_assignment_mutable { + no_copy_assignment_mutable& + operator=(no_copy_assignment_mutable const&) = default; + no_copy_assignment_mutable& operator=(no_copy_assignment_mutable&) = delete; + no_copy_assignment_mutable& operator=(no_copy_assignment_mutable&&) = default; +}; + +struct derived_from_noncopyable : std::unique_ptr {}; + +struct has_noncopyable { + std::unique_ptr x; +}; + +struct const_copy_assignment { + const_copy_assignment(const_copy_assignment const&); + const_copy_assignment(const_copy_assignment&&); + + const_copy_assignment& operator=(const_copy_assignment&&); + const_copy_assignment const& operator=(const_copy_assignment const&) const; +}; + +struct volatile_copy_assignment { + volatile_copy_assignment(volatile_copy_assignment volatile&); + volatile_copy_assignment(volatile_copy_assignment volatile&&); + + volatile_copy_assignment& operator=(volatile_copy_assignment&&); + volatile_copy_assignment volatile& + operator=(volatile_copy_assignment const&) volatile; +}; + +struct cv_copy_assignment { + cv_copy_assignment(cv_copy_assignment const volatile&); + cv_copy_assignment(cv_copy_assignment const volatile&&); + + cv_copy_assignment const volatile& + operator=(cv_copy_assignment const volatile&) const volatile; + cv_copy_assignment const volatile& + operator=(cv_copy_assignment const volatile&&) const volatile; +}; + +#endif // TEST_STD_CONCEPTS_OBJECT_COPYABLE_H diff --git a/libcxx/test/std/concepts/object/copyable.compile.pass.cpp b/libcxx/test/std/concepts/object/copyable.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/concepts/object/copyable.compile.pass.cpp @@ -0,0 +1,118 @@ +//===----------------------------------------------------------------------===// +// +// 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 copyable = see below; + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "copyable.h" + +static_assert(std::copyable); +static_assert(std::copyable); +static_assert(std::copyable); +static_assert(std::copyable); +static_assert(std::copyable); +static_assert(std::copyable); +static_assert(std::copyable); + +struct S {}; +static_assert(std::copyable); +static_assert(std::copyable); +static_assert(std::copyable); +static_assert(std::copyable); +static_assert(std::copyable); +static_assert(std::copyable); +static_assert(std::copyable); +static_assert(std::copyable); +static_assert(std::copyable); +static_assert(std::copyable); +static_assert(std::copyable); +static_assert(std::copyable); +static_assert(std::copyable); +static_assert(std::copyable); +static_assert(std::copyable); +static_assert(std::copyable); +static_assert(std::copyable); +static_assert(std::copyable); +static_assert(std::copyable); +static_assert(std::copyable); +static_assert(std::copyable); +static_assert(std::copyable); +static_assert(std::copyable); +static_assert(std::copyable); +static_assert(std::copyable); +static_assert(std::copyable); + +static_assert(std::copyable >); +static_assert(std::copyable >); +static_assert(std::copyable >); +static_assert(std::copyable >); +static_assert(std::copyable > >); +static_assert(std::copyable > >); +static_assert(std::copyable >); +static_assert(std::copyable > >); + +static_assert(std::copyable); +static_assert(std::copyable); + +// Not objects +static_assert(!std::copyable); +static_assert(!std::copyable); +static_assert(!std::copyable); +static_assert(!std::copyable); +static_assert(!std::copyable); +static_assert(!std::copyable); +static_assert(!std::copyable); +static_assert(!std::copyable); +static_assert(!std::copyable); +static_assert(!std::copyable); +static_assert(!std::copyable); +static_assert(!std::copyable); + +// Not copy constructible or copy assignable +static_assert(!std::copyable >); + +// Not assignable +static_assert(!std::copyable); +static_assert(!std::copyable); +static_assert(std::copyable); +static_assert(!std::copyable); +static_assert(std::copyable); + +static_assert(!std::copyable); +static_assert(!std::copyable); + +static_assert(std::is_copy_assignable_v); +static_assert(!std::copyable); +static_assert(!std::copyable); +static_assert(!std::copyable); +static_assert(!std::copyable); +static_assert(!std::copyable); +static_assert(!std::copyable); +static_assert(!std::copyable); +static_assert(!std::copyable); + +static_assert( + !std::assignable_from); +static_assert(!std::copyable); + +int main(int, char**) { return 0; }