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,555 @@ +//===----------------------------------------------------------------------===// +// +// 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../support/allocators.h" + +// Note: is_lvalue_reference is checked in all ModelsAssignableFrom calls. +template +constexpr void NeverAssignableFrom() { + 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); +} + +template +constexpr bool CheckAssignableFromRvalues() { + NeverAssignableFrom(); + + constexpr auto Result = std::assignable_from; + static_assert(std::assignable_from == Result); + + return Result; +} + +template +constexpr bool CheckAssignableFromLvalues() { + NeverAssignableFrom(); + + constexpr auto Result = std::assignable_from; + static_assert(std::assignable_from == Result); + static_assert(std::assignable_from == Result); + + return Result; +} + +template +constexpr bool CheckAssignableFromLvaluesAndRvalues() { + return CheckAssignableFromLvalues() && + CheckAssignableFromRvalues(); +} + +namespace BuiltinTypes { +static_assert(CheckAssignableFromLvaluesAndRvalues()); +static_assert(CheckAssignableFromLvaluesAndRvalues()); +static_assert(CheckAssignableFromLvaluesAndRvalues()); +static_assert(CheckAssignableFromLvaluesAndRvalues()); +static_assert(!CheckAssignableFromLvaluesAndRvalues()); +static_assert(!CheckAssignableFromLvaluesAndRvalues()); +static_assert( + !CheckAssignableFromLvaluesAndRvalues()); +static_assert(CheckAssignableFromLvaluesAndRvalues()); +static_assert(CheckAssignableFromLvaluesAndRvalues()); +static_assert( + !CheckAssignableFromLvaluesAndRvalues()); +static_assert( + !CheckAssignableFromLvaluesAndRvalues()); +static_assert(CheckAssignableFromLvaluesAndRvalues()); +static_assert( + !CheckAssignableFromLvaluesAndRvalues()); +static_assert( + CheckAssignableFromLvaluesAndRvalues()); +static_assert(!CheckAssignableFromLvaluesAndRvalues()); +static_assert( + CheckAssignableFromLvaluesAndRvalues()); +static_assert( + CheckAssignableFromLvaluesAndRvalues()); +static_assert( + CheckAssignableFromLvaluesAndRvalues()); +static_assert(CheckAssignableFromLvaluesAndRvalues()); + +static_assert(CheckAssignableFromLvaluesAndRvalues()); +static_assert( + CheckAssignableFromLvaluesAndRvalues()); +static_assert( + !CheckAssignableFromLvaluesAndRvalues()); + +struct S {}; +static_assert(CheckAssignableFromLvaluesAndRvalues()); +static_assert(CheckAssignableFromLvaluesAndRvalues()); +static_assert( + CheckAssignableFromLvaluesAndRvalues()); +static_assert(CheckAssignableFromLvaluesAndRvalues()); +static_assert(CheckAssignableFromLvaluesAndRvalues()); +static_assert(CheckAssignableFromLvaluesAndRvalues< + int (S::*)() const, int (S::*)() const noexcept>()); +static_assert(CheckAssignableFromLvaluesAndRvalues()); +static_assert(CheckAssignableFromLvaluesAndRvalues< + int (S::*)() volatile, int (S::*)() volatile noexcept>()); +static_assert(CheckAssignableFromLvaluesAndRvalues< + int (S::*)() const volatile, int (S::*)() const volatile>()); +static_assert( + CheckAssignableFromLvaluesAndRvalues< + int (S::*)() const volatile, int (S::*)() const volatile noexcept>()); + +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); +} // namespace BuiltinTypes + +namespace TypesFitForPurpose { +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); +} // namespace TypesFitForPurpose + +namespace StandardTypes { +static_assert( + CheckAssignableFromLvaluesAndRvalues, std::deque >()); +static_assert(!CheckAssignableFromLvaluesAndRvalues, + std::deque >()); +static_assert(!CheckAssignableFromLvaluesAndRvalues< + std::deque, std::deque > >()); +static_assert(!CheckAssignableFromLvaluesAndRvalues, + std::vector >()); +static_assert(!CheckAssignableFromLvaluesAndRvalues, int>()); + +static_assert(CheckAssignableFromLvaluesAndRvalues, + std::forward_list >()); +static_assert(!CheckAssignableFromLvaluesAndRvalues< + std::forward_list, std::forward_list >()); +static_assert(!CheckAssignableFromLvaluesAndRvalues< + std::forward_list, std::forward_list > >()); +static_assert(!CheckAssignableFromLvaluesAndRvalues, + std::vector >()); +static_assert( + !CheckAssignableFromLvaluesAndRvalues, int>()); + +static_assert( + CheckAssignableFromLvaluesAndRvalues, std::list >()); +static_assert(!CheckAssignableFromLvaluesAndRvalues, + std::list >()); +static_assert(!CheckAssignableFromLvaluesAndRvalues< + std::list, std::list > >()); +static_assert( + !CheckAssignableFromLvaluesAndRvalues, std::vector >()); +static_assert(!CheckAssignableFromLvaluesAndRvalues, int>()); + +static_assert(CheckAssignableFromLvaluesAndRvalues, + std::map >()); +static_assert(!CheckAssignableFromLvaluesAndRvalues< + std::map, std::map >()); +static_assert(!CheckAssignableFromLvaluesAndRvalues< + std::map, + std::map > > >()); +static_assert(!CheckAssignableFromLvaluesAndRvalues< + std::map, std::unordered_map >()); +static_assert(!CheckAssignableFromLvaluesAndRvalues, + std::pair >()); + +#ifndef _LIBCPP_HAS_NO_THREADS +static_assert(!CheckAssignableFromRvalues()); +static_assert(!CheckAssignableFromLvalues()); +#endif + +static_assert(CheckAssignableFromLvaluesAndRvalues, int>()); +static_assert( + CheckAssignableFromLvaluesAndRvalues, double>()); +static_assert(CheckAssignableFromLvaluesAndRvalues, + std::optional >()); +static_assert( + !CheckAssignableFromLvaluesAndRvalues >()); +static_assert( + !CheckAssignableFromLvaluesAndRvalues >()); + +static_assert( + !std::common_reference_with, std::optional >); +static_assert( + !CheckAssignableFromRvalues, std::optional >()); +static_assert( + !CheckAssignableFromLvalues, std::optional >()); + +static_assert(CheckAssignableFromLvaluesAndRvalues()); +static_assert( + CheckAssignableFromLvaluesAndRvalues()); +static_assert(CheckAssignableFromLvaluesAndRvalues()); +static_assert(CheckAssignableFromLvaluesAndRvalues()); +static_assert(!CheckAssignableFromLvaluesAndRvalues< + std::string, std::basic_string >()); +static_assert( + !CheckAssignableFromLvaluesAndRvalues >()); + +static_assert( + CheckAssignableFromLvaluesAndRvalues()); +static_assert( + CheckAssignableFromLvaluesAndRvalues()); +static_assert(CheckAssignableFromLvaluesAndRvalues()); +static_assert( + CheckAssignableFromLvaluesAndRvalues()); +static_assert(!CheckAssignableFromLvaluesAndRvalues< + std::string_view, std::basic_string_view >()); + +static_assert( + CheckAssignableFromRvalues, std::unique_ptr >()); +static_assert( + !CheckAssignableFromLvalues, std::unique_ptr >()); + +static_assert( + CheckAssignableFromLvaluesAndRvalues, + std::unordered_map >()); +static_assert(!CheckAssignableFromLvaluesAndRvalues< + std::unordered_map, + std::unordered_map >()); +static_assert(!CheckAssignableFromLvaluesAndRvalues< + std::unordered_map, + std::unordered_map > > >()); +static_assert(!CheckAssignableFromLvaluesAndRvalues< + std::unordered_map, std::map >()); +static_assert(!CheckAssignableFromLvaluesAndRvalues< + std::unordered_map, std::pair >()); + +static_assert(CheckAssignableFromLvaluesAndRvalues, + std::vector >()); +static_assert(!CheckAssignableFromLvaluesAndRvalues, + std::vector >()); +static_assert(!CheckAssignableFromLvaluesAndRvalues< + std::vector, std::vector > >()); +static_assert(!CheckAssignableFromLvaluesAndRvalues, + std::deque >()); +static_assert(!CheckAssignableFromLvaluesAndRvalues, int>()); +} // namespace StandardTypes + +int main(int, char**) { return 0; }