//===----------------------------------------------------------------------===//
//
// 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
// template<class LHS, class RHS>
// concept assignable_from =
// std::is_lvalue_reference_v<LHS> &&
// std::common_reference_with<
// const std::remove_reference_t<LHS>&,
// const std::remove_reference_t<RHS>&> &&
// requires (LHS lhs, RHS&& rhs) {
// { lhs = std::forward<RHS>(rhs) } -> std::same_as<LHS>;
// };
#include <concepts>
#include <type_traits>
#include "MoveOnly.h"
struct NoCommonRef {
NoCommonRef& operator=(const int&);
};
static_assert(std::is_assignable_v<NoCommonRef&, const int&>);
static_assert(!std::assignable_from<NoCommonRef&, const int&>); // no common reference type
struct Base {};
struct Derived : Base {};
static_assert(!std::assignable_from<Base*, Derived*>);
static_assert( std::assignable_from<Base*&, Derived*>);
static_assert( std::assignable_from<Base*&, Derived*&>);
static_assert( std::assignable_from<Base*&, Derived*&&>);
static_assert( std::assignable_from<Base*&, Derived* const>);
static_assert( std::assignable_from<Base*&, Derived* const&>);
static_assert( std::assignable_from<Base*&, Derived* const&&>);
static_assert(!std::assignable_from<Base*&, const Derived*>);
static_assert(!std::assignable_from<Base*&, const Derived*&>);
static_assert(!std::assignable_from<Base*&, const Derived*&&>);
static_assert(!std::assignable_from<Base*&, const Derived* const>);
static_assert(!std::assignable_from<Base*&, const Derived* const&>);
static_assert(!std::assignable_from<Base*&, const Derived* const&&>);
static_assert( std::assignable_from<const Base*&, Derived*>);
static_assert( std::assignable_from<const Base*&, Derived*&>);
static_assert( std::assignable_from<const Base*&, Derived*&&>);
static_assert( std::assignable_from<const Base*&, Derived* const>);
static_assert( std::assignable_from<const Base*&, Derived* const&>);
static_assert( std::assignable_from<const Base*&, Derived* const&&>);
static_assert( std::assignable_from<const Base*&, const Derived*>);
static_assert( std::assignable_from<const Base*&, const Derived*&>);
static_assert( std::assignable_from<const Base*&, const Derived*&&>);
static_assert( std::assignable_from<const Base*&, const Derived* const>);
static_assert( std::assignable_from<const Base*&, const Derived* const&>);
static_assert( std::assignable_from<const Base*&, const Derived* const&&>);
struct VoidResultType {
void operator=(const VoidResultType&);
};
static_assert(std::is_assignable_v<VoidResultType&, const VoidResultType&>);
static_assert(!std::assignable_from<VoidResultType&, const VoidResultType&>);
struct ValueResultType {
ValueResultType operator=(const ValueResultType&);
};
static_assert(std::is_assignable_v<ValueResultType&, const ValueResultType&>);
static_assert(!std::assignable_from<ValueResultType&, const ValueResultType&>);
struct Locale {
const Locale& operator=(const Locale&);
};
static_assert(std::is_assignable_v<Locale&, const Locale&>);
static_assert(!std::assignable_from<Locale&, const Locale&>);
struct Tuple {
Tuple& operator=(const Tuple&);
const Tuple& operator=(const Tuple&) const;
};
static_assert(!std::assignable_from<Tuple, const Tuple&>);
static_assert( std::assignable_from<Tuple&, const Tuple&>);
static_assert(!std::assignable_from<Tuple&&, const Tuple&>);
static_assert(!std::assignable_from<const Tuple, const Tuple&>);
static_assert( std::assignable_from<const Tuple&, const Tuple&>);
static_assert(!std::assignable_from<const Tuple&&, const Tuple&>);
// Finally, check a few simple cases.
static_assert( std::assignable_from<int&, int>);
static_assert( std::assignable_from<int&, int&>);
static_assert( std::assignable_from<int&, int&&>);
static_assert(!std::assignable_from<const int&, int>);
static_assert(!std::assignable_from<const int&, int&>);
static_assert(!std::assignable_from<const int&, int&&>);
static_assert( std::assignable_from<volatile int&, int>);
static_assert( std::assignable_from<volatile int&, int&>);
static_assert( std::assignable_from<volatile int&, int&&>);
static_assert(!std::assignable_from<int(&)[10], int>);
static_assert(!std::assignable_from<int(&)[10], int(&)[10]>);
static_assert( std::assignable_from<MoveOnly&, MoveOnly>);
static_assert(!std::assignable_from<MoveOnly&, MoveOnly&>);
static_assert( std::assignable_from<MoveOnly&, MoveOnly&&>);
static_assert(!std::assignable_from<void, int>);
static_assert(!std::assignable_from<void, void>);