diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst index 3c635e5e46bbd..61805726a4ff0 100644 --- a/libcxx/docs/FeatureTestMacroTable.rst +++ b/libcxx/docs/FeatureTestMacroTable.rst @@ -198,6 +198,10 @@ Status ---------------------------------------------------------- ----------------- ``__cpp_lib_char8_t`` ``201907L`` ---------------------------------------------------------- ----------------- + ``__cpp_lib_common_reference`` ``202302L`` + ---------------------------------------------------------- ----------------- + ``__cpp_lib_common_reference_wrapper`` ``202302L`` + ---------------------------------------------------------- ----------------- ``__cpp_lib_concepts`` ``202002L`` ---------------------------------------------------------- ----------------- ``__cpp_lib_constexpr_algorithms`` ``201806L`` diff --git a/libcxx/docs/ReleaseNotes/21.rst b/libcxx/docs/ReleaseNotes/21.rst index 08b32bb508dc1..e7ac03de80ac0 100644 --- a/libcxx/docs/ReleaseNotes/21.rst +++ b/libcxx/docs/ReleaseNotes/21.rst @@ -51,6 +51,7 @@ Implemented Papers - P2441R2: ``views::join_with`` (`Github `__) - P2711R1: Making multi-param constructors of ``views`` ``explicit`` (`Github `__) - P2770R0: Stashing stashing ``iterators`` for proper flattening (`Github `__) +- P2655R3: ``common_reference_t`` of ``reference_wrapper`` Should Be a Reference Type (`Github `__) Improvements and New Features ----------------------------- diff --git a/libcxx/docs/Status/Cxx23Papers.csv b/libcxx/docs/Status/Cxx23Papers.csv index 574675175a4cf..e4fa07d82289d 100644 --- a/libcxx/docs/Status/Cxx23Papers.csv +++ b/libcxx/docs/Status/Cxx23Papers.csv @@ -113,7 +113,7 @@ "`P2693R1 `__","Formatting ``thread::id`` and ``stacktrace``","2023-02 (Issaquah)","|Partial|","","The formatter for ``stacktrace`` is not implemented, since ``stacktrace`` is not implemented yet" "`P2679R2 `__","Fixing ``std::start_lifetime_as`` for arrays","2023-02 (Issaquah)","","","" "`P2674R1 `__","A trait for implicit lifetime types","2023-02 (Issaquah)","|Complete|","20","" -"`P2655R3 `__","``common_reference_t`` of ``reference_wrapper`` Should Be a Reference Type","2023-02 (Issaquah)","","","" +"`P2655R3 `__","``common_reference_t`` of ``reference_wrapper`` Should Be a Reference Type","2023-02 (Issaquah)","|Complete|","21","The paper is implemented as a DR to C++20" "`P2652R2 `__","Disallow User Specialization of ``allocator_traits``","2023-02 (Issaquah)","|Complete|","19","" "`P2787R1 `__","``pmr::generator`` - Promise Types are not Values","2023-02 (Issaquah)","","","" "`P2614R2 `__","Deprecate ``numeric_limits::has_denorm``","2023-02 (Issaquah)","|Complete|","18","" diff --git a/libcxx/include/__functional/reference_wrapper.h b/libcxx/include/__functional/reference_wrapper.h index 11ba364369428..148703b21d84a 100644 --- a/libcxx/include/__functional/reference_wrapper.h +++ b/libcxx/include/__functional/reference_wrapper.h @@ -11,15 +11,18 @@ #define _LIBCPP___FUNCTIONAL_REFERENCE_WRAPPER_H #include <__compare/synth_three_way.h> +#include <__concepts/convertible_to.h> #include <__config> #include <__functional/weak_result_type.h> #include <__memory/addressof.h> +#include <__type_traits/common_reference.h> #include <__type_traits/desugars_to.h> #include <__type_traits/enable_if.h> #include <__type_traits/invoke.h> #include <__type_traits/is_const.h> #include <__type_traits/is_core_convertible.h> #include <__type_traits/is_same.h> +#include <__type_traits/is_specialization.h> #include <__type_traits/remove_cvref.h> #include <__type_traits/void_t.h> #include <__utility/declval.h> @@ -156,6 +159,32 @@ template inline const bool __desugars_to_v<_CanonicalTag, reference_wrapper<_Operation>, _Args...> = __desugars_to_v<_CanonicalTag, _Operation, _Args...>; +#if _LIBCPP_STD_VER >= 20 + +template +inline constexpr bool __is_ref_wrapper = __is_specialization_v<_Tp, reference_wrapper>; + +template +concept __ref_wrap_common_reference_exists_with = __is_ref_wrapper<_Rp> && requires { + typename common_reference_t; +} && convertible_to<_RpQual, common_reference_t>; + +template class _RpQual, template class _TpQual> + requires(__ref_wrap_common_reference_exists_with<_Rp, _Tp, _RpQual<_Rp>, _TpQual<_Tp>> && + !__ref_wrap_common_reference_exists_with<_Tp, _Rp, _TpQual<_Tp>, _RpQual<_Rp>>) +struct basic_common_reference<_Rp, _Tp, _RpQual, _TpQual> { + using type _LIBCPP_NODEBUG = common_reference_t>; +}; + +template class _TpQual, template class _RpQual> + requires(__ref_wrap_common_reference_exists_with<_Rp, _Tp, _RpQual<_Rp>, _TpQual<_Tp>> && + !__ref_wrap_common_reference_exists_with<_Tp, _Rp, _TpQual<_Tp>, _RpQual<_Rp>>) +struct basic_common_reference<_Tp, _Rp, _TpQual, _RpQual> { + using type _LIBCPP_NODEBUG = common_reference_t>; +}; + +#endif // _LIBCPP_STD_VER >= 20 + _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP___FUNCTIONAL_REFERENCE_WRAPPER_H diff --git a/libcxx/include/__type_traits/common_reference.h b/libcxx/include/__type_traits/common_reference.h index 7df55f7fecfd5..59badb64267de 100644 --- a/libcxx/include/__type_traits/common_reference.h +++ b/libcxx/include/__type_traits/common_reference.h @@ -10,6 +10,7 @@ #define _LIBCPP___TYPE_TRAITS_COMMON_REFERENCE_H #include <__config> +#include <__type_traits/add_pointer.h> #include <__type_traits/common_type.h> #include <__type_traits/copy_cv.h> #include <__type_traits/copy_cvref.h> @@ -139,13 +140,17 @@ struct __common_reference_sub_bullet2 : __common_reference_sub_bullet3<_Tp, _Up> template struct __common_reference_sub_bullet1 : __common_reference_sub_bullet2<_Tp, _Up> {}; -// sub-bullet 1 - If T1 and T2 are reference types and COMMON-REF(T1, T2) is well-formed, then -// the member typedef `type` denotes that type. +// sub-bullet 1 - Let R be COMMON-REF(T1, T2). If T1 and T2 are reference types, R is well-formed, and +// is_convertible_v, add_pointer_t> && is_convertible_v, add_pointer_t> is +// true, then the member typedef type denotes R. + template struct common_reference<_Tp, _Up> : __common_reference_sub_bullet1<_Tp, _Up> {}; template - requires is_reference_v<_Tp> && is_reference_v<_Up> && requires { typename __common_ref_t<_Tp, _Up>; } + requires is_reference_v<_Tp> && is_reference_v<_Up> && requires { typename __common_ref_t<_Tp, _Up>; } && + is_convertible_v, add_pointer_t<__common_ref_t<_Tp, _Up>>> && + is_convertible_v, add_pointer_t<__common_ref_t<_Tp, _Up>>> struct __common_reference_sub_bullet1<_Tp, _Up> { using type _LIBCPP_NODEBUG = __common_ref_t<_Tp, _Up>; }; diff --git a/libcxx/include/functional b/libcxx/include/functional index c72d0931e4b92..9ebcd818ec840 100644 --- a/libcxx/include/functional +++ b/libcxx/include/functional @@ -565,6 +565,7 @@ POLICY: For non-variadic implementations, the number of arguments is limited # include <__functional/bind_front.h> # include <__functional/identity.h> # include <__functional/ranges_operations.h> +# include <__type_traits/common_reference.h> # include <__type_traits/unwrap_ref.h> # endif diff --git a/libcxx/include/version b/libcxx/include/version index 91fe48351e161..d98049bd57046 100644 --- a/libcxx/include/version +++ b/libcxx/include/version @@ -59,6 +59,8 @@ __cpp_lib_char8_t 201907L __cpp_lib_chrono_udls 201304L __cpp_lib_clamp 201603L +__cpp_lib_common_reference 202302L +__cpp_lib_common_reference_wrapper 202302L __cpp_lib_complex_udls 201309L __cpp_lib_concepts 202002L __cpp_lib_constexpr_algorithms 202306L @@ -402,6 +404,8 @@ __cpp_lib_void_t 201411L # if _LIBCPP_HAS_CHAR8_T # define __cpp_lib_char8_t 201907L # endif +# define __cpp_lib_common_reference 202302L +# define __cpp_lib_common_reference_wrapper 202302L # define __cpp_lib_concepts 202002L # define __cpp_lib_constexpr_algorithms 201806L # define __cpp_lib_constexpr_complex 201711L diff --git a/libcxx/modules/std/functional.inc b/libcxx/modules/std/functional.inc index ddc7d023ee6dc..9ef8f584611fc 100644 --- a/libcxx/modules/std/functional.inc +++ b/libcxx/modules/std/functional.inc @@ -14,6 +14,10 @@ export namespace std { using std::invoke_r; #endif +#if _LIBCPP_STD_VER >= 20 + using std::basic_common_reference; +#endif + // [refwrap], reference_wrapper using std::reference_wrapper; diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/functional.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/functional.version.compile.pass.cpp index 8dbbbf432ddbf..8c0820681188d 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/functional.version.compile.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/functional.version.compile.pass.cpp @@ -32,6 +32,10 @@ # error "__cpp_lib_boyer_moore_searcher should not be defined before c++17" # endif +# ifdef __cpp_lib_common_reference_wrapper +# error "__cpp_lib_common_reference_wrapper should not be defined before c++20" +# endif + # ifdef __cpp_lib_constexpr_functional # error "__cpp_lib_constexpr_functional should not be defined before c++20" # endif @@ -94,6 +98,10 @@ # error "__cpp_lib_boyer_moore_searcher should not be defined before c++17" # endif +# ifdef __cpp_lib_common_reference_wrapper +# error "__cpp_lib_common_reference_wrapper should not be defined before c++20" +# endif + # ifdef __cpp_lib_constexpr_functional # error "__cpp_lib_constexpr_functional should not be defined before c++20" # endif @@ -165,6 +173,10 @@ # error "__cpp_lib_boyer_moore_searcher should have the value 201603L in c++17" # endif +# ifdef __cpp_lib_common_reference_wrapper +# error "__cpp_lib_common_reference_wrapper should not be defined before c++20" +# endif + # ifdef __cpp_lib_constexpr_functional # error "__cpp_lib_constexpr_functional should not be defined before c++20" # endif @@ -245,6 +257,13 @@ # error "__cpp_lib_boyer_moore_searcher should have the value 201603L in c++20" # endif +# ifndef __cpp_lib_common_reference_wrapper +# error "__cpp_lib_common_reference_wrapper should be defined in c++20" +# endif +# if __cpp_lib_common_reference_wrapper != 202302L +# error "__cpp_lib_common_reference_wrapper should have the value 202302L in c++20" +# endif + # ifndef __cpp_lib_constexpr_functional # error "__cpp_lib_constexpr_functional should be defined in c++20" # endif @@ -337,6 +356,13 @@ # error "__cpp_lib_boyer_moore_searcher should have the value 201603L in c++23" # endif +# ifndef __cpp_lib_common_reference_wrapper +# error "__cpp_lib_common_reference_wrapper should be defined in c++23" +# endif +# if __cpp_lib_common_reference_wrapper != 202302L +# error "__cpp_lib_common_reference_wrapper should have the value 202302L in c++23" +# endif + # ifndef __cpp_lib_constexpr_functional # error "__cpp_lib_constexpr_functional should be defined in c++23" # endif @@ -441,6 +467,13 @@ # error "__cpp_lib_boyer_moore_searcher should have the value 201603L in c++26" # endif +# ifndef __cpp_lib_common_reference_wrapper +# error "__cpp_lib_common_reference_wrapper should be defined in c++26" +# endif +# if __cpp_lib_common_reference_wrapper != 202302L +# error "__cpp_lib_common_reference_wrapper should have the value 202302L in c++26" +# endif + # ifndef __cpp_lib_constexpr_functional # error "__cpp_lib_constexpr_functional should be defined in c++26" # endif diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/type_traits.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/type_traits.version.compile.pass.cpp index 45c51b5807c69..e6c0940ab7fd5 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/type_traits.version.compile.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/type_traits.version.compile.pass.cpp @@ -28,6 +28,10 @@ # error "__cpp_lib_bounded_array_traits should not be defined before c++20" # endif +# ifdef __cpp_lib_common_reference +# error "__cpp_lib_common_reference should not be defined before c++20" +# endif + # ifdef __cpp_lib_has_unique_object_representations # error "__cpp_lib_has_unique_object_representations should not be defined before c++17" # endif @@ -130,6 +134,10 @@ # error "__cpp_lib_bounded_array_traits should not be defined before c++20" # endif +# ifdef __cpp_lib_common_reference +# error "__cpp_lib_common_reference should not be defined before c++20" +# endif + # ifdef __cpp_lib_has_unique_object_representations # error "__cpp_lib_has_unique_object_representations should not be defined before c++17" # endif @@ -250,6 +258,10 @@ # error "__cpp_lib_bounded_array_traits should not be defined before c++20" # endif +# ifdef __cpp_lib_common_reference +# error "__cpp_lib_common_reference should not be defined before c++20" +# endif + # ifndef __cpp_lib_has_unique_object_representations # error "__cpp_lib_has_unique_object_representations should be defined in c++17" # endif @@ -394,6 +406,13 @@ # error "__cpp_lib_bounded_array_traits should have the value 201902L in c++20" # endif +# ifndef __cpp_lib_common_reference +# error "__cpp_lib_common_reference should be defined in c++20" +# endif +# if __cpp_lib_common_reference != 202302L +# error "__cpp_lib_common_reference should have the value 202302L in c++20" +# endif + # ifndef __cpp_lib_has_unique_object_representations # error "__cpp_lib_has_unique_object_representations should be defined in c++20" # endif @@ -568,6 +587,13 @@ # error "__cpp_lib_bounded_array_traits should have the value 201902L in c++23" # endif +# ifndef __cpp_lib_common_reference +# error "__cpp_lib_common_reference should be defined in c++23" +# endif +# if __cpp_lib_common_reference != 202302L +# error "__cpp_lib_common_reference should have the value 202302L in c++23" +# endif + # ifndef __cpp_lib_has_unique_object_representations # error "__cpp_lib_has_unique_object_representations should be defined in c++23" # endif @@ -763,6 +789,13 @@ # error "__cpp_lib_bounded_array_traits should have the value 201902L in c++26" # endif +# ifndef __cpp_lib_common_reference +# error "__cpp_lib_common_reference should be defined in c++26" +# endif +# if __cpp_lib_common_reference != 202302L +# error "__cpp_lib_common_reference should have the value 202302L in c++26" +# endif + # ifndef __cpp_lib_has_unique_object_representations # error "__cpp_lib_has_unique_object_representations should be defined in c++26" # endif diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp index e546719142231..222d562a19d63 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp @@ -164,6 +164,14 @@ # error "__cpp_lib_clamp should not be defined before c++17" # endif +# ifdef __cpp_lib_common_reference +# error "__cpp_lib_common_reference should not be defined before c++20" +# endif + +# ifdef __cpp_lib_common_reference_wrapper +# error "__cpp_lib_common_reference_wrapper should not be defined before c++20" +# endif + # ifdef __cpp_lib_complex_udls # error "__cpp_lib_complex_udls should not be defined before c++14" # endif @@ -1057,6 +1065,14 @@ # error "__cpp_lib_clamp should not be defined before c++17" # endif +# ifdef __cpp_lib_common_reference +# error "__cpp_lib_common_reference should not be defined before c++20" +# endif + +# ifdef __cpp_lib_common_reference_wrapper +# error "__cpp_lib_common_reference_wrapper should not be defined before c++20" +# endif + # ifndef __cpp_lib_complex_udls # error "__cpp_lib_complex_udls should be defined in c++14" # endif @@ -2055,6 +2071,14 @@ # error "__cpp_lib_clamp should have the value 201603L in c++17" # endif +# ifdef __cpp_lib_common_reference +# error "__cpp_lib_common_reference should not be defined before c++20" +# endif + +# ifdef __cpp_lib_common_reference_wrapper +# error "__cpp_lib_common_reference_wrapper should not be defined before c++20" +# endif + # ifndef __cpp_lib_complex_udls # error "__cpp_lib_complex_udls should be defined in c++17" # endif @@ -3281,6 +3305,20 @@ # error "__cpp_lib_clamp should have the value 201603L in c++20" # endif +# ifndef __cpp_lib_common_reference +# error "__cpp_lib_common_reference should be defined in c++20" +# endif +# if __cpp_lib_common_reference != 202302L +# error "__cpp_lib_common_reference should have the value 202302L in c++20" +# endif + +# ifndef __cpp_lib_common_reference_wrapper +# error "__cpp_lib_common_reference_wrapper should be defined in c++20" +# endif +# if __cpp_lib_common_reference_wrapper != 202302L +# error "__cpp_lib_common_reference_wrapper should have the value 202302L in c++20" +# endif + # ifndef __cpp_lib_complex_udls # error "__cpp_lib_complex_udls should be defined in c++20" # endif @@ -4726,6 +4764,20 @@ # error "__cpp_lib_clamp should have the value 201603L in c++23" # endif +# ifndef __cpp_lib_common_reference +# error "__cpp_lib_common_reference should be defined in c++23" +# endif +# if __cpp_lib_common_reference != 202302L +# error "__cpp_lib_common_reference should have the value 202302L in c++23" +# endif + +# ifndef __cpp_lib_common_reference_wrapper +# error "__cpp_lib_common_reference_wrapper should be defined in c++23" +# endif +# if __cpp_lib_common_reference_wrapper != 202302L +# error "__cpp_lib_common_reference_wrapper should have the value 202302L in c++23" +# endif + # ifndef __cpp_lib_complex_udls # error "__cpp_lib_complex_udls should be defined in c++23" # endif @@ -6399,6 +6451,20 @@ # error "__cpp_lib_clamp should have the value 201603L in c++26" # endif +# ifndef __cpp_lib_common_reference +# error "__cpp_lib_common_reference should be defined in c++26" +# endif +# if __cpp_lib_common_reference != 202302L +# error "__cpp_lib_common_reference should have the value 202302L in c++26" +# endif + +# ifndef __cpp_lib_common_reference_wrapper +# error "__cpp_lib_common_reference_wrapper should be defined in c++26" +# endif +# if __cpp_lib_common_reference_wrapper != 202302L +# error "__cpp_lib_common_reference_wrapper should have the value 202302L in c++26" +# endif + # ifndef __cpp_lib_complex_udls # error "__cpp_lib_complex_udls should be defined in c++26" # endif diff --git a/libcxx/test/std/utilities/function.objects/refwrap/common_reference.compile.pass.cpp b/libcxx/test/std/utilities/function.objects/refwrap/common_reference.compile.pass.cpp new file mode 100644 index 0000000000000..a3630cb0017b6 --- /dev/null +++ b/libcxx/test/std/utilities/function.objects/refwrap/common_reference.compile.pass.cpp @@ -0,0 +1,152 @@ +//===----------------------------------------------------------------------===// +// +// 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&>); diff --git a/libcxx/test/std/utilities/meta/meta.trans/meta.trans.other/common_reference.compile.pass.cpp b/libcxx/test/std/utilities/meta/meta.trans/meta.trans.other/common_reference.compile.pass.cpp index e802776f52bfc..8e3cad797d5a7 100644 --- a/libcxx/test/std/utilities/meta/meta.trans/meta.trans.other/common_reference.compile.pass.cpp +++ b/libcxx/test/std/utilities/meta/meta.trans/meta.trans.other/common_reference.compile.pass.cpp @@ -18,9 +18,7 @@ #include "test_macros.h" template -constexpr bool has_type = requires { - typename T::type; -}; +constexpr bool has_type = requires { typename T::type; }; // A slightly simplified variation of std::tuple template @@ -74,8 +72,10 @@ static_assert(std::is_same_v, void (&&)()>) // -- Otherwise, if sizeof...(T) is two, let T1 and T2 denote the two types in // the pack T. Then // (6.3.1) -// -- If T1 and T2 are reference types and COMMON_REF(T1, T2) is well-formed, -// then the member typedef type denotes that type. +// -- Let R be COMMON-REF(T1, T2). If T1 and T2 are reference types, R is well-formed, +// and is_convertible_v, add_pointer_t> && is_convertible_v, add_pointer_t> +// is true, then the member typedef type denotes R. + struct B {}; struct D : B {}; static_assert(std::is_same_v, B&>); @@ -99,7 +99,19 @@ static_assert(std::is_same_v, static_assert(std::is_same_v, int const volatile&&>); static_assert(std::is_same_v, int const (&)[10]>); -static_assert(std::is_same_v, int const volatile (&)[10]>); +static_assert( + std::is_same_v, int const volatile (&)[10]>); + +// when conversion from pointers are not true +struct E {}; +struct F { + operator E&() const; +}; + +static_assert(!std::is_convertible_v); + +// The following should not use 6.3.1, but fallback to 6.3.3 +static_assert(std::is_same_v, E&>); // (6.3.2) // -- Otherwise, if basic_common_reference, @@ -136,8 +148,8 @@ static_assert(std::is_same_v, MyIntRef>) // -- Otherwise, if common_type_t is well-formed, then the member // typedef type denotes that type. struct moveonly { - moveonly() = default; - moveonly(moveonly&&) = default; + moveonly() = default; + moveonly(moveonly&&) = default; moveonly& operator=(moveonly&&) = default; }; struct moveonly2 : moveonly {}; @@ -169,14 +181,17 @@ static_assert(!has_type >); #if TEST_STD_VER > 20 static_assert(std::is_same_v>, std::tuple>); -static_assert(std::is_same_v, std::tuple>, std::tuple>); +static_assert( + std::is_same_v, std::tuple>, std::tuple>); static_assert(std::is_same_v, std::tuple>, std::tuple>); static_assert(std::is_same_v, std::tuple>, std::tuple>); -static_assert(std::is_same_v, std::tuple>, - std::tuple>); -static_assert(!has_type, std::tuple>>); +static_assert( + std::is_same_v, std::tuple>, + std::tuple>); +static_assert( + !has_type, std::tuple>>); static_assert(std::is_same_v, std::tuple>, std::tuple>); static_assert(std::is_same_v, std::tuple>, std::tuple>); @@ -185,26 +200,25 @@ static_assert(!has_type, std::tuple, int, X2>>); struct A {}; -template class TQual, template class UQual> +template