diff --git a/libcxx/include/concepts b/libcxx/include/concepts --- a/libcxx/include/concepts +++ b/libcxx/include/concepts @@ -210,6 +210,15 @@ template concept floating_point = is_floating_point_v<_Tp>; +// [concept.assignable] +template +concept assignable_from = + is_lvalue_reference_v<_Lhs> && + common_reference_with&, const remove_reference_t<_Rhs>&> && + requires (_Lhs __lhs, _Rhs&& __rhs) { + { __lhs = _VSTD::forward<_Rhs>(__rhs) } -> same_as<_Lhs>; + }; + // [concept.destructible] template diff --git a/libcxx/test/std/concepts/lang/assignable.compile.pass.cpp b/libcxx/test/std/concepts/lang/assignable.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/concepts/lang/assignable.compile.pass.cpp @@ -0,0 +1,393 @@ +//===----------------------------------------------------------------------===// +// +// 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 assignable_from; + +#include +#include + +// Note: is_lvalue_reference is checked in all ModelsAssignableFrom calls. +template +constexpr bool ModelsAssignableFrom() { + static_assert(!std::assignable_from); + static_assert(!std::assignable_from); + static_assert(!std::assignable_from); + static_assert(!std::assignable_from); + static_assert(!std::assignable_from); + static_assert(!std::assignable_from); + static_assert(!std::assignable_from); + static_assert(!std::assignable_from); + static_assert(!std::assignable_from); + static_assert(!std::assignable_from); + + static_assert(std::assignable_from); + static_assert(std::assignable_from); + static_assert(std::assignable_from); + static_assert(std::assignable_from); + static_assert(std::assignable_from); + static_assert(std::assignable_from); + static_assert(std::assignable_from); + static_assert(std::assignable_from); + static_assert(std::assignable_from); + static_assert(std::assignable_from); + + static_assert(!std::assignable_from); + static_assert(!std::assignable_from); + static_assert(!std::assignable_from); + static_assert(!std::assignable_from); + static_assert(!std::assignable_from); + static_assert(!std::assignable_from); + static_assert(!std::assignable_from); + static_assert(!std::assignable_from); + static_assert(!std::assignable_from); + static_assert(!std::assignable_from); + + static_assert(std::assignable_from); + static_assert(std::assignable_from); + static_assert(std::assignable_from); + static_assert(std::assignable_from); + static_assert(std::assignable_from); + static_assert(std::assignable_from); + static_assert(std::assignable_from); + static_assert(std::assignable_from); + static_assert(std::assignable_from); + static_assert(std::assignable_from); + + static_assert(!std::assignable_from); + static_assert(!std::assignable_from); + static_assert(!std::assignable_from); + static_assert(!std::assignable_from); + static_assert(!std::assignable_from); + static_assert(!std::assignable_from); + static_assert(!std::assignable_from); + static_assert(!std::assignable_from); + static_assert(!std::assignable_from); + static_assert(!std::assignable_from); + + static_assert(!std::assignable_from); + static_assert(!std::assignable_from); + static_assert(!std::assignable_from); + static_assert(!std::assignable_from); + static_assert(!std::assignable_from); + static_assert(!std::assignable_from); + static_assert(!std::assignable_from); + static_assert(!std::assignable_from); + static_assert(!std::assignable_from); + static_assert(!std::assignable_from); + + static_assert(!std::assignable_from); + static_assert(!std::assignable_from); + static_assert(!std::assignable_from); + static_assert(!std::assignable_from); + static_assert(!std::assignable_from); + static_assert(!std::assignable_from); + static_assert(!std::assignable_from); + static_assert(!std::assignable_from); + static_assert(!std::assignable_from); + static_assert(!std::assignable_from); + + static_assert(!std::assignable_from); + static_assert(!std::assignable_from); + static_assert(!std::assignable_from); + static_assert(!std::assignable_from); + static_assert(!std::assignable_from); + static_assert(!std::assignable_from); + static_assert(!std::assignable_from); + static_assert(!std::assignable_from); + static_assert(!std::assignable_from); + static_assert(!std::assignable_from); + + static_assert(!std::assignable_from); + static_assert(!std::assignable_from); + static_assert(!std::assignable_from); + static_assert(!std::assignable_from); + static_assert(!std::assignable_from); + static_assert(!std::assignable_from); + static_assert(!std::assignable_from); + static_assert(!std::assignable_from); + static_assert(!std::assignable_from); + static_assert( + !std::assignable_from); + + return std::assignable_from; +} + +// Built-in types +static_assert(ModelsAssignableFrom()); +static_assert(ModelsAssignableFrom()); +static_assert(ModelsAssignableFrom()); + +static_assert(ModelsAssignableFrom()); +static_assert(!std::assignable_from); +static_assert(!std::assignable_from); +static_assert(!std::assignable_from); +static_assert(ModelsAssignableFrom()); +static_assert(ModelsAssignableFrom()); +static_assert(!std::assignable_from); +static_assert(!std::assignable_from); +static_assert(ModelsAssignableFrom()); +static_assert(!std::assignable_from); +static_assert(ModelsAssignableFrom()); +static_assert(!std::assignable_from); +static_assert(ModelsAssignableFrom()); +static_assert(ModelsAssignableFrom()); +static_assert(ModelsAssignableFrom()); +static_assert(ModelsAssignableFrom()); + +static_assert(ModelsAssignableFrom()); +static_assert(ModelsAssignableFrom()); + +struct S {}; +static_assert(ModelsAssignableFrom()); +static_assert(ModelsAssignableFrom()); +static_assert(ModelsAssignableFrom()); +static_assert(ModelsAssignableFrom()); +static_assert(ModelsAssignableFrom()); +static_assert( + ModelsAssignableFrom()); +static_assert( + ModelsAssignableFrom()); +static_assert(ModelsAssignableFrom()); +static_assert(ModelsAssignableFrom()); +static_assert(ModelsAssignableFrom()); + +static_assert(!std::assignable_from); +static_assert(!std::assignable_from); +static_assert(!std::assignable_from); +static_assert(!std::assignable_from); +static_assert(!std::assignable_from); +static_assert(!std::assignable_from); +static_assert(!std::assignable_from); +static_assert(!std::assignable_from); +static_assert( + !std::assignable_from); +static_assert( + !std::assignable_from); +static_assert(!std::assignable_from); +static_assert( + !std::assignable_from); +static_assert(!std::assignable_from); +static_assert(!std::assignable_from); + +struct T1 {}; + +struct NoCommonReference {}; +static_assert(!std::common_reference_with); +static_assert(!std::assignable_from); + +struct AssignmentReturnsNonReference { + AssignmentReturnsNonReference operator=(T1); + operator T1() const; +}; +static_assert(std::common_reference_with); +static_assert(!std::assignable_from); + +struct NonCVAssignmentOnly { + NonCVAssignmentOnly& operator=(T1); + operator T1() const; +}; +static_assert( + std::common_reference_with); +static_assert(std::assignable_from); +static_assert(!std::assignable_from); +static_assert(!std::assignable_from); +static_assert(!std::assignable_from); + +struct NonCVAssignmentOnlyConstQualified { + NonCVAssignmentOnlyConstQualified& operator=(T1) const; + operator T1() const; +}; +static_assert(std::common_reference_with< + const T1&, const NonCVAssignmentOnlyConstQualified&>); +static_assert(std::assignable_from); +static_assert( + !std::assignable_from); +static_assert( + !std::assignable_from); +static_assert(!std::assignable_from< + const volatile NonCVAssignmentOnlyConstQualified&, T1>); + +struct NonCVAssignmentVolatileQualified { + NonCVAssignmentVolatileQualified& operator=(T1) volatile; + operator T1() const volatile; +}; +static_assert(std::common_reference_with< + const T1&, const NonCVAssignmentVolatileQualified&>); +static_assert(std::assignable_from); +static_assert( + !std::assignable_from); +static_assert( + !std::assignable_from); +static_assert(!std::assignable_from< + const volatile NonCVAssignmentVolatileQualified&, T1>); + +struct NonCVAssignmentOnlyCVQualified { + NonCVAssignmentOnlyCVQualified& operator=(T1) const volatile; + operator T1() const volatile; +}; +static_assert(std::common_reference_with< + const T1&, const NonCVAssignmentOnlyCVQualified&>); +static_assert(std::assignable_from); +static_assert(!std::assignable_from); +static_assert( + !std::assignable_from); +static_assert( + !std::assignable_from); + +struct ConstAssignmentOnly { + const ConstAssignmentOnly& operator=(T1) const; + operator T1() const; +}; +static_assert( + std::common_reference_with); +static_assert(std::assignable_from); +static_assert(!std::assignable_from); +static_assert(!std::assignable_from); +static_assert(!std::assignable_from); + +struct VolatileAssignmentOnly { + volatile VolatileAssignmentOnly& operator=(T1) volatile; + operator T1() const volatile; +}; +static_assert( + std::common_reference_with); +static_assert(!std::assignable_from); +static_assert(std::assignable_from); + +struct CVAssignmentOnly { + const volatile CVAssignmentOnly& operator=(T1) const volatile; + operator T1() const volatile; +}; +static_assert(std::common_reference_with); +static_assert(std::assignable_from); +static_assert(!std::assignable_from); +static_assert(!std::assignable_from); +static_assert(!std::assignable_from); + +struct LvalueRefQualifiedWithRvalueT1Only { + LvalueRefQualifiedWithRvalueT1Only& operator=(T1&&) &; + const LvalueRefQualifiedWithRvalueT1Only& operator=(T1&&) const&; + volatile LvalueRefQualifiedWithRvalueT1Only& operator=(T1&&) volatile&; + const volatile LvalueRefQualifiedWithRvalueT1Only& operator=(T1&&) const + volatile&; + operator T1() const volatile; +}; +static_assert(std::common_reference_with< + const T1&, const LvalueRefQualifiedWithRvalueT1Only&>); +static_assert(std::assignable_from); +static_assert( + std::assignable_from); +static_assert( + std::assignable_from); +static_assert(std::assignable_from< + const volatile LvalueRefQualifiedWithRvalueT1Only&, T1&&>); +static_assert(!std::assignable_from); +static_assert( + !std::assignable_from); +static_assert( + !std::assignable_from); +static_assert(!std::assignable_from< + const volatile LvalueRefQualifiedWithRvalueT1Only&, T1&>); +static_assert( + !std::assignable_from); +static_assert(!std::assignable_from); +static_assert(!std::assignable_from< + volatile LvalueRefQualifiedWithRvalueT1Only&, const T1&>); +static_assert(!std::assignable_from< + const volatile LvalueRefQualifiedWithRvalueT1Only&, const T1&>); +static_assert( + !std::assignable_from); +static_assert(!std::assignable_from); +static_assert(!std::assignable_from< + volatile LvalueRefQualifiedWithRvalueT1Only&, volatile T1&>); +static_assert( + !std::assignable_from); +static_assert(!std::assignable_from); +static_assert(!std::assignable_from); +static_assert( + !std::assignable_from); +static_assert( + !std::assignable_from); +static_assert( + !std::assignable_from); +static_assert(!std::assignable_from); +static_assert(!std::assignable_from< + volatile LvalueRefQualifiedWithRvalueT1Only&, const T1&&>); +static_assert(!std::assignable_from< + const volatile LvalueRefQualifiedWithRvalueT1Only&, const T1&&>); +static_assert( + !std::assignable_from); +static_assert(!std::assignable_from); +static_assert(!std::assignable_from< + volatile LvalueRefQualifiedWithRvalueT1Only&, volatile T1&&>); +static_assert( + !std::assignable_from); +static_assert(!std::assignable_from); +static_assert(!std::assignable_from); +static_assert( + !std::assignable_from); +static_assert( + !std::assignable_from); + +struct NoLvalueRefAssignment { + NoLvalueRefAssignment& operator=(T1) &&; + const NoLvalueRefAssignment& operator=(T1) const&&; + volatile NoLvalueRefAssignment& operator=(T1) volatile&&; + const volatile NoLvalueRefAssignment& operator=(T1) const volatile&&; + operator T1() const volatile; +}; +static_assert( + std::common_reference_with); +static_assert(!std::assignable_from); +static_assert(!std::assignable_from); +static_assert(!std::assignable_from); +static_assert(!std::assignable_from); +static_assert(!std::assignable_from); +static_assert(!std::assignable_from); +static_assert(!std::assignable_from); +static_assert( + !std::assignable_from); +static_assert(!std::assignable_from); +static_assert(!std::assignable_from); +static_assert( + !std::assignable_from); +static_assert( + !std::assignable_from); +static_assert(!std::assignable_from); +static_assert( + !std::assignable_from); +static_assert( + !std::assignable_from); +static_assert(!std::assignable_from); + +int main(int, char**) { return 0; }