124dd2d2fSChristopher Di Bella //===----------------------------------------------------------------------===//
224dd2d2fSChristopher Di Bella //
324dd2d2fSChristopher Di Bella // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
424dd2d2fSChristopher Di Bella // See https://llvm.org/LICENSE.txt for license information.
524dd2d2fSChristopher Di Bella // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
624dd2d2fSChristopher Di Bella //
724dd2d2fSChristopher Di Bella //===----------------------------------------------------------------------===//
824dd2d2fSChristopher Di Bella 
924dd2d2fSChristopher Di Bella // UNSUPPORTED: c++03, c++11, c++14, c++17
1024dd2d2fSChristopher Di Bella 
11*d96a5042SArthur O'Dwyer // template<class LHS, class RHS>
12*d96a5042SArthur O'Dwyer // concept assignable_from =
13*d96a5042SArthur O'Dwyer //   std::is_lvalue_reference_v<LHS> &&
14*d96a5042SArthur O'Dwyer //   std::common_reference_with<
15*d96a5042SArthur O'Dwyer //     const std::remove_reference_t<LHS>&,
16*d96a5042SArthur O'Dwyer //     const std::remove_reference_t<RHS>&> &&
17*d96a5042SArthur O'Dwyer //   requires (LHS lhs, RHS&& rhs) {
18*d96a5042SArthur O'Dwyer //     { lhs = std::forward<RHS>(rhs) } -> std::same_as<LHS>;
19*d96a5042SArthur O'Dwyer //   };
2024dd2d2fSChristopher Di Bella 
2124dd2d2fSChristopher Di Bella #include <concepts>
22*d96a5042SArthur O'Dwyer #include <type_traits>
2324dd2d2fSChristopher Di Bella 
24*d96a5042SArthur O'Dwyer #include "MoveOnly.h"
2524dd2d2fSChristopher Di Bella 
26*d96a5042SArthur O'Dwyer struct NoCommonRef {
27*d96a5042SArthur O'Dwyer   NoCommonRef& operator=(const int&);
28*d96a5042SArthur O'Dwyer };
29*d96a5042SArthur O'Dwyer static_assert(std::is_assignable_v<NoCommonRef&, const int&>);
30*d96a5042SArthur O'Dwyer static_assert(!std::assignable_from<NoCommonRef&, const int&>); // no common reference type
31e1ce3dabSLouis Dionne 
32*d96a5042SArthur O'Dwyer struct Base {};
33*d96a5042SArthur O'Dwyer struct Derived : Base {};
34*d96a5042SArthur O'Dwyer static_assert(!std::assignable_from<Base*, Derived*>);
35*d96a5042SArthur O'Dwyer static_assert( std::assignable_from<Base*&, Derived*>);
36*d96a5042SArthur O'Dwyer static_assert( std::assignable_from<Base*&, Derived*&>);
37*d96a5042SArthur O'Dwyer static_assert( std::assignable_from<Base*&, Derived*&&>);
38*d96a5042SArthur O'Dwyer static_assert( std::assignable_from<Base*&, Derived* const>);
39*d96a5042SArthur O'Dwyer static_assert( std::assignable_from<Base*&, Derived* const&>);
40*d96a5042SArthur O'Dwyer static_assert( std::assignable_from<Base*&, Derived* const&&>);
41*d96a5042SArthur O'Dwyer static_assert(!std::assignable_from<Base*&, const Derived*>);
42*d96a5042SArthur O'Dwyer static_assert(!std::assignable_from<Base*&, const Derived*&>);
43*d96a5042SArthur O'Dwyer static_assert(!std::assignable_from<Base*&, const Derived*&&>);
44*d96a5042SArthur O'Dwyer static_assert(!std::assignable_from<Base*&, const Derived* const>);
45*d96a5042SArthur O'Dwyer static_assert(!std::assignable_from<Base*&, const Derived* const&>);
46*d96a5042SArthur O'Dwyer static_assert(!std::assignable_from<Base*&, const Derived* const&&>);
47*d96a5042SArthur O'Dwyer static_assert( std::assignable_from<const Base*&, Derived*>);
48*d96a5042SArthur O'Dwyer static_assert( std::assignable_from<const Base*&, Derived*&>);
49*d96a5042SArthur O'Dwyer static_assert( std::assignable_from<const Base*&, Derived*&&>);
50*d96a5042SArthur O'Dwyer static_assert( std::assignable_from<const Base*&, Derived* const>);
51*d96a5042SArthur O'Dwyer static_assert( std::assignable_from<const Base*&, Derived* const&>);
52*d96a5042SArthur O'Dwyer static_assert( std::assignable_from<const Base*&, Derived* const&&>);
53*d96a5042SArthur O'Dwyer static_assert( std::assignable_from<const Base*&, const Derived*>);
54*d96a5042SArthur O'Dwyer static_assert( std::assignable_from<const Base*&, const Derived*&>);
55*d96a5042SArthur O'Dwyer static_assert( std::assignable_from<const Base*&, const Derived*&&>);
56*d96a5042SArthur O'Dwyer static_assert( std::assignable_from<const Base*&, const Derived* const>);
57*d96a5042SArthur O'Dwyer static_assert( std::assignable_from<const Base*&, const Derived* const&>);
58*d96a5042SArthur O'Dwyer static_assert( std::assignable_from<const Base*&, const Derived* const&&>);
5924dd2d2fSChristopher Di Bella 
60*d96a5042SArthur O'Dwyer struct VoidResultType {
61*d96a5042SArthur O'Dwyer     void operator=(const VoidResultType&);
62*d96a5042SArthur O'Dwyer };
63*d96a5042SArthur O'Dwyer static_assert(std::is_assignable_v<VoidResultType&, const VoidResultType&>);
64*d96a5042SArthur O'Dwyer static_assert(!std::assignable_from<VoidResultType&, const VoidResultType&>);
6524dd2d2fSChristopher Di Bella 
66*d96a5042SArthur O'Dwyer struct ValueResultType {
67*d96a5042SArthur O'Dwyer     ValueResultType operator=(const ValueResultType&);
68*d96a5042SArthur O'Dwyer };
69*d96a5042SArthur O'Dwyer static_assert(std::is_assignable_v<ValueResultType&, const ValueResultType&>);
70*d96a5042SArthur O'Dwyer static_assert(!std::assignable_from<ValueResultType&, const ValueResultType&>);
7124dd2d2fSChristopher Di Bella 
72*d96a5042SArthur O'Dwyer struct Locale {
73*d96a5042SArthur O'Dwyer     const Locale& operator=(const Locale&);
74*d96a5042SArthur O'Dwyer };
75*d96a5042SArthur O'Dwyer static_assert(std::is_assignable_v<Locale&, const Locale&>);
76*d96a5042SArthur O'Dwyer static_assert(!std::assignable_from<Locale&, const Locale&>);
7724dd2d2fSChristopher Di Bella 
78*d96a5042SArthur O'Dwyer struct Tuple {
79*d96a5042SArthur O'Dwyer     Tuple& operator=(const Tuple&);
80*d96a5042SArthur O'Dwyer     const Tuple& operator=(const Tuple&) const;
81*d96a5042SArthur O'Dwyer };
82*d96a5042SArthur O'Dwyer static_assert(!std::assignable_from<Tuple, const Tuple&>);
83*d96a5042SArthur O'Dwyer static_assert( std::assignable_from<Tuple&, const Tuple&>);
84*d96a5042SArthur O'Dwyer static_assert(!std::assignable_from<Tuple&&, const Tuple&>);
85*d96a5042SArthur O'Dwyer static_assert(!std::assignable_from<const Tuple, const Tuple&>);
86*d96a5042SArthur O'Dwyer static_assert( std::assignable_from<const Tuple&, const Tuple&>);
87*d96a5042SArthur O'Dwyer static_assert(!std::assignable_from<const Tuple&&, const Tuple&>);
8824dd2d2fSChristopher Di Bella 
89*d96a5042SArthur O'Dwyer // Finally, check a few simple cases.
90*d96a5042SArthur O'Dwyer static_assert( std::assignable_from<int&, int>);
91*d96a5042SArthur O'Dwyer static_assert( std::assignable_from<int&, int&>);
92*d96a5042SArthur O'Dwyer static_assert( std::assignable_from<int&, int&&>);
93*d96a5042SArthur O'Dwyer static_assert(!std::assignable_from<const int&, int>);
94*d96a5042SArthur O'Dwyer static_assert(!std::assignable_from<const int&, int&>);
95*d96a5042SArthur O'Dwyer static_assert(!std::assignable_from<const int&, int&&>);
96*d96a5042SArthur O'Dwyer static_assert( std::assignable_from<volatile int&, int>);
97*d96a5042SArthur O'Dwyer static_assert( std::assignable_from<volatile int&, int&>);
98*d96a5042SArthur O'Dwyer static_assert( std::assignable_from<volatile int&, int&&>);
99*d96a5042SArthur O'Dwyer static_assert(!std::assignable_from<int(&)[10], int>);
100*d96a5042SArthur O'Dwyer static_assert(!std::assignable_from<int(&)[10], int(&)[10]>);
101*d96a5042SArthur O'Dwyer static_assert( std::assignable_from<MoveOnly&, MoveOnly>);
102*d96a5042SArthur O'Dwyer static_assert(!std::assignable_from<MoveOnly&, MoveOnly&>);
103*d96a5042SArthur O'Dwyer static_assert( std::assignable_from<MoveOnly&, MoveOnly&&>);
10424dd2d2fSChristopher Di Bella static_assert(!std::assignable_from<void, int>);
10524dd2d2fSChristopher Di Bella static_assert(!std::assignable_from<void, void>);
106