//===----------------------------------------------------------------------===// // // 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 // // common_reference specializations for reference_wrapper #include #include #include template concept HasType = requires { typename T::type; }; template concept check_XY = std::same_as>; template concept check_YX = std::same_as>; template concept check = check_XY && check_YX; template concept check_none_XY = !HasType>; template concept check_none_YX = !HasType>; template concept check_none = check_none_XY && check_none_YX; // https://eel.is/c++draft/meta.trans#other-2.4 template using CondRes = decltype(false ? std::declval()() : std::declval()()); template struct Ternary {}; template requires requires() { typename CondRes; } struct Ternary { using type = CondRes; }; template using Ternary_t = typename Ternary::type; template using Ref = std::reference_wrapper; using std::common_reference_t; using std::same_as; // clang-format off static_assert(check, int & >); static_assert(check, int const& >); static_assert(check, int & >); static_assert(check, int const& >); static_assert(check const&, int& >); static_assert(check, const volatile int&>); // derived-base and implicit convertibles struct B {}; struct D : B {}; struct C { operator B&() const; }; static_assert(check, D & >); static_assert(check, D const&>); static_assert(check, D const&>); static_assert(check, B & >); static_assert(check, B const&>); static_assert(check, B const&>); static_assert(std::same_as, B&>>); static_assert(std::same_as, B const &>>); static_assert(std::same_as, B const&>>); static_assert( check , C& >); static_assert( check , C >); static_assert( check, C >); static_assert(!check , B& >); // Ref cannot be converted to B& static_assert( check , C const&>); // was const B& before P2655R3 using Ri = Ref; using RRi = Ref>; using RRRi = Ref>>; static_assert(check); static_assert(check); static_assert(check); static_assert(check); static_assert(check_none); static_assert(check_none); static_assert(check_none); static_assert(check_none); static_assert(check_none); static_assert(check_none); template struct Test { // Check that reference_wrapper behaves the same as T& in common_reference. using R1 = common_reference_t; using R2 = common_reference_t; using R3 = common_reference_t; using R4 = common_reference_t; using R5 = common_reference_t; static_assert(same_as, T&>>); static_assert(same_as, T const&>>); static_assert(same_as, T&&>>); static_assert(same_as, T const&&>>); static_assert(same_as, T>>); // commute: static_assert(same_as>>); static_assert(same_as>>); static_assert(same_as>>); static_assert(same_as>>); static_assert(same_as>>); // reference qualification of reference_wrapper is irrelevant static_assert(same_as&, T&>>); static_assert(same_as , T&>>); static_assert(same_as const&, T&>>); static_assert(same_as&&, T&>>); static_assert(same_as const&&, T&>>); }; // clang-format on // Instantiate above checks: template struct Test; template struct Test>; // reference_wrapper as both args is unaffected. // subject to simple first rule of static_assert(check&, Ref&, Ref&>); // double wrap is unaffected. static_assert(check&, Ref>, Ref&>);