//===----------------------------------------------------------------------===// // // 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 // type_traits // common_reference #include #include #include #include "test_macros.h" template constexpr bool has_type = requires { typename T::type; }; // A slightly simplified variation of std::tuple template struct UserTuple {}; template struct Tuple_helper {}; template struct Tuple_helper...>, UserTuple, UserTuple > { using type = UserTuple...>; }; template class TQual, template class UQual> struct std::basic_common_reference< ::UserTuple, ::UserTuple, TQual, UQual> : ::Tuple_helper...>, UserTuple...> > {}; struct X2 {}; struct Y2 {}; struct Z2 {}; template <> struct std::common_type { using type = Z2; }; template <> struct std::common_type { using type = Z2; }; // (6.1) // -- If sizeof...(T) is zero, there shall be no member type. static_assert(!has_type >); // (6.2) // -- Otherwise, if sizeof...(T) is one, let T0 denote the sole type in the // pack T. The member typedef type shall denote the same type as T0. static_assert(std::is_same_v, void>); static_assert(std::is_same_v, int>); static_assert(std::is_same_v, int&>); static_assert(std::is_same_v, int&&>); static_assert(std::is_same_v, int const>); static_assert(std::is_same_v, int const&>); static_assert(std::is_same_v, int const&&>); static_assert(std::is_same_v, int volatile[]>); static_assert(std::is_same_v, int volatile (&)[]>); static_assert(std::is_same_v, int volatile (&&)[]>); static_assert(std::is_same_v, void (&)()>); static_assert(std::is_same_v, void (&&)()>); // (6.3) // -- 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. struct B {}; struct D : B {}; static_assert(std::is_same_v, B&>); static_assert(std::is_same_v, B const&>); static_assert(std::is_same_v, B const&>); static_assert(std::is_same_v, B const&>); static_assert(std::is_same_v, B&>); static_assert(std::is_same_v, B&&>); static_assert(std::is_same_v, B const&&>); static_assert(std::is_same_v, B const&&>); static_assert(std::is_same_v, B const&>); static_assert(std::is_same_v, B const&>); static_assert(std::is_same_v, B const&>); static_assert(std::is_same_v, B const&>); static_assert(std::is_same_v, B const&>); static_assert(std::is_same_v, B const&>); static_assert(std::is_same_v, int const volatile&>); 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]>); // (6.3.2) // -- Otherwise, if basic_common_reference, // remove_cvref_t, XREF(T1), XREF(T2)>::type is well-formed, then the // member typedef type denotes that type. static_assert(std::is_same_v&, UserTuple>, UserTuple>); static_assert(std::is_same_v&, const UserTuple&>, const volatile UserTuple&>); // (6.3.3) // -- Otherwise, if COND_RES(T1, T2) is well-formed, then the member typedef // type denotes that type. static_assert(std::is_same_v, void>); static_assert(std::is_same_v, int>); static_assert(std::is_same_v, int>); static_assert(std::is_same_v, int>); static_assert(std::is_same_v, int>); // tricky volatile reference case static_assert(std::is_same_v, int>); static_assert(std::is_same_v, int>); static_assert(std::is_same_v, int*>); // https://github.com/ericniebler/stl2/issues/338 struct MyIntRef { MyIntRef(int&); }; static_assert(std::is_same_v, MyIntRef>); // (6.3.4) // -- Otherwise, if common_type_t is well-formed, then the member // typedef type denotes that type. struct moveonly { moveonly() = default; moveonly(moveonly&&) = default; moveonly& operator=(moveonly&&) = default; }; struct moveonly2 : moveonly {}; static_assert(std::is_same_v, moveonly>); static_assert(std::is_same_v, moveonly>); static_assert(std::is_same_v, moveonly>); static_assert(std::is_same_v, Z2>); // (6.3.5) // -- Otherwise, there shall be no member type. static_assert(!has_type&, const UserTuple&> >); // (6.4) // -- Otherwise, if sizeof...(T) is greater than two, let T1, T2, and Rest, // respectively, denote the first, second, and (pack of) remaining types // comprising T. Let C be the type common_reference_t. Then: // (6.4.1) // -- If there is such a type C, the member typedef type shall denote the // same type, if any, as common_reference_t. static_assert(std::is_same_v, int>); static_assert(std::is_same_v, int const volatile&>); static_assert(std::is_same_v, float>); // (6.4.2) // -- Otherwise, there shall be no member type. 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(!has_type, 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(!has_type, std::tuple>>); static_assert(!has_type, int, X2>>); struct A {}; template class TQual, template class UQual> struct std::basic_common_reference, TQual, UQual> { using type = tuple>; }; static_assert(std::is_same_v, std::tuple>, std::tuple>); static_assert(std::is_same_v>, std::pair>); static_assert(std::is_same_v, std::pair>, std::pair>); static_assert(std::is_same_v, std::pair>, std::pair>); static_assert(std::is_same_v, std::pair>, std::pair>); static_assert(std::is_same_v, std::pair>, std::pair>); static_assert(!has_type, std::pair>>); static_assert(std::is_same_v, std::pair>, std::pair>); static_assert(std::is_same_v, std::pair>, std::pair>); static_assert(!has_type, std::pair>>); static_assert(!has_type, std::pair>>); static_assert(!has_type, int, X2>>); #endif