
We pretty consistently don't define those cause they are not needed, and it removes the potential pitfall to think that these tests are being run. This doesn't touch .compile.fail.cpp tests since those should be replaced by .verify.cpp tests anyway, and there would be a lot to fix up. As a fly-by, I also fixed a bit of formatting, removed a few unused includes and made some very minor, clearly NFC refactorings such as in allocator.traits/allocator.traits.members/allocate.verify.cpp where the old test basically made no sense the way it was written. Differential Revision: https://reviews.llvm.org/D146236
993 lines
31 KiB
C++
993 lines
31 KiB
C++
//===----------------------------------------------------------------------===//
|
|
//
|
|
// 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 From, class To>
|
|
// concept common_with;
|
|
|
|
#include <concepts>
|
|
#include <type_traits>
|
|
|
|
#include "test_macros.h"
|
|
|
|
template <class T, class U>
|
|
constexpr bool CheckCommonWith() noexcept {
|
|
constexpr bool result = std::common_with<T, U>;
|
|
static_assert(std::common_with<T, U&> == result);
|
|
static_assert(std::common_with<T, const U&> == result);
|
|
static_assert(std::common_with<T, volatile U&> == result);
|
|
static_assert(std::common_with<T, const volatile U&> == result);
|
|
static_assert(std::common_with<T, U&&> == result);
|
|
static_assert(std::common_with<T, const U&&> == result);
|
|
static_assert(std::common_with<T, volatile U&&> == result);
|
|
static_assert(std::common_with<T, const volatile U&&> == result);
|
|
static_assert(std::common_with<T&, U&&> == result);
|
|
static_assert(std::common_with<T&, const U&&> == result);
|
|
static_assert(std::common_with<T&, volatile U&&> == result);
|
|
static_assert(std::common_with<T&, const volatile U&&> == result);
|
|
static_assert(std::common_with<const T&, U&&> == result);
|
|
static_assert(std::common_with<const T&, const U&&> == result);
|
|
static_assert(std::common_with<const T&, volatile U&&> == result);
|
|
static_assert(std::common_with<const T&, const volatile U&&> == result);
|
|
static_assert(std::common_with<volatile T&, U&&> == result);
|
|
static_assert(std::common_with<volatile T&, const U&&> == result);
|
|
static_assert(std::common_with<volatile T&, volatile U&&> == result);
|
|
static_assert(std::common_with<volatile T&, const volatile U&&> == result);
|
|
static_assert(std::common_with<const volatile T&, U&&> == result);
|
|
static_assert(std::common_with<const volatile T&, const U&&> == result);
|
|
static_assert(std::common_with<const volatile T&, volatile U&&> == result);
|
|
static_assert(std::common_with<const volatile T&, const volatile U&&> ==
|
|
result);
|
|
return result;
|
|
}
|
|
|
|
template <class T, class U>
|
|
constexpr bool HasValidCommonType() noexcept {
|
|
return requires { typename std::common_type_t<T, U>; }
|
|
&&std::same_as<std::common_type_t<T, U>, std::common_type_t<U, T> >;
|
|
}
|
|
|
|
namespace BuiltinTypes {
|
|
// fundamental types
|
|
static_assert(std::common_with<void, void>);
|
|
static_assert(CheckCommonWith<int, int>());
|
|
static_assert(CheckCommonWith<int, long>());
|
|
static_assert(CheckCommonWith<int, unsigned char>());
|
|
#ifndef TEST_HAS_NO_INT128
|
|
static_assert(CheckCommonWith<int, __int128_t>());
|
|
#endif
|
|
static_assert(CheckCommonWith<int, double>());
|
|
|
|
// arrays
|
|
static_assert(CheckCommonWith<int[5], int[5]>());
|
|
|
|
// pointers
|
|
static_assert(CheckCommonWith<int*, int*>());
|
|
static_assert(CheckCommonWith<int*, const int*>());
|
|
static_assert(CheckCommonWith<int*, volatile int*>());
|
|
static_assert(CheckCommonWith<int*, const volatile int*>());
|
|
static_assert(CheckCommonWith<const int*, const int*>());
|
|
static_assert(CheckCommonWith<const int*, volatile int*>());
|
|
static_assert(CheckCommonWith<const int*, const volatile int*>());
|
|
static_assert(CheckCommonWith<volatile int*, const int*>());
|
|
static_assert(CheckCommonWith<volatile int*, volatile int*>());
|
|
static_assert(CheckCommonWith<volatile int*, const volatile int*>());
|
|
static_assert(CheckCommonWith<const volatile int*, const int*>());
|
|
static_assert(CheckCommonWith<const volatile int*, volatile int*>());
|
|
static_assert(CheckCommonWith<const volatile int*, const volatile int*>());
|
|
|
|
static_assert(CheckCommonWith<int (*)(), int (*)()>());
|
|
static_assert(CheckCommonWith<int (*)(), int (*)() noexcept>());
|
|
static_assert(CheckCommonWith<int (&)(), int (&)()>());
|
|
static_assert(CheckCommonWith<int (&)(), int (&)() noexcept>());
|
|
static_assert(CheckCommonWith<int (&)(), int (*)()>());
|
|
static_assert(CheckCommonWith<int (&)(), int (*)() noexcept>());
|
|
|
|
struct S {};
|
|
static_assert(CheckCommonWith<int S::*, int S::*>());
|
|
static_assert(CheckCommonWith<int S::*, const int S::*>());
|
|
static_assert(CheckCommonWith<int (S::*)(), int (S::*)()>());
|
|
static_assert(CheckCommonWith<int (S::*)(), int (S::*)() noexcept>());
|
|
static_assert(CheckCommonWith<int (S::*)() const, int (S::*)() const>());
|
|
static_assert(
|
|
CheckCommonWith<int (S::*)() const, int (S::*)() const noexcept>());
|
|
static_assert(CheckCommonWith<int (S::*)() volatile, int (S::*)() volatile>());
|
|
static_assert(
|
|
CheckCommonWith<int (S::*)() volatile, int (S::*)() volatile noexcept>());
|
|
static_assert(CheckCommonWith<int (S::*)() const volatile,
|
|
int (S::*)() const volatile>());
|
|
static_assert(CheckCommonWith<int (S::*)() const volatile,
|
|
int (S::*)() const volatile noexcept>());
|
|
|
|
// nonsense
|
|
static_assert(!CheckCommonWith<double, float*>());
|
|
static_assert(!CheckCommonWith<int, int[5]>());
|
|
static_assert(!CheckCommonWith<int*, long*>());
|
|
static_assert(!CheckCommonWith<int*, unsigned int*>());
|
|
static_assert(!CheckCommonWith<int (*)(), int (*)(int)>());
|
|
static_assert(!CheckCommonWith<int S::*, float S::*>());
|
|
static_assert(!CheckCommonWith<int (S::*)(), int (S::*)() const>());
|
|
static_assert(!CheckCommonWith<int (S::*)(), int (S::*)() volatile>());
|
|
static_assert(!CheckCommonWith<int (S::*)(), int (S::*)() const volatile>());
|
|
static_assert(!CheckCommonWith<int (S::*)() const, int (S::*)() volatile>());
|
|
static_assert(
|
|
!CheckCommonWith<int (S::*)() const, int (S::*)() const volatile>());
|
|
static_assert(
|
|
!CheckCommonWith<int (S::*)() volatile, int (S::*)() const volatile>());
|
|
} // namespace BuiltinTypes
|
|
|
|
namespace NoDefaultCommonType {
|
|
class T {};
|
|
|
|
static_assert(!CheckCommonWith<T, int>());
|
|
static_assert(!CheckCommonWith<int, T>());
|
|
static_assert(!CheckCommonWith<T, int[10]>());
|
|
static_assert(!CheckCommonWith<T[10], int>());
|
|
static_assert(!CheckCommonWith<T*, int*>());
|
|
static_assert(!CheckCommonWith<T*, const int*>());
|
|
static_assert(!CheckCommonWith<T*, volatile int*>());
|
|
static_assert(!CheckCommonWith<T*, const volatile int*>());
|
|
static_assert(!CheckCommonWith<const T*, int*>());
|
|
static_assert(!CheckCommonWith<volatile T*, int*>());
|
|
static_assert(!CheckCommonWith<const volatile T*, int*>());
|
|
static_assert(!CheckCommonWith<const T*, const int*>());
|
|
static_assert(!CheckCommonWith<const T*, volatile int*>());
|
|
static_assert(!CheckCommonWith<const T*, const volatile int*>());
|
|
static_assert(!CheckCommonWith<const T*, const int*>());
|
|
static_assert(!CheckCommonWith<volatile T*, const int*>());
|
|
static_assert(!CheckCommonWith<const volatile T*, const int*>());
|
|
static_assert(!CheckCommonWith<volatile T*, const int*>());
|
|
static_assert(!CheckCommonWith<volatile T*, volatile int*>());
|
|
static_assert(!CheckCommonWith<volatile T*, const volatile int*>());
|
|
static_assert(!CheckCommonWith<const T*, volatile int*>());
|
|
static_assert(!CheckCommonWith<volatile T*, volatile int*>());
|
|
static_assert(!CheckCommonWith<const volatile T*, volatile int*>());
|
|
static_assert(!CheckCommonWith<const volatile T*, const int*>());
|
|
static_assert(!CheckCommonWith<const volatile T*, volatile int*>());
|
|
static_assert(!CheckCommonWith<const volatile T*, const volatile int*>());
|
|
static_assert(!CheckCommonWith<const T*, const volatile int*>());
|
|
static_assert(!CheckCommonWith<volatile T*, const volatile int*>());
|
|
static_assert(!CheckCommonWith<const volatile T*, const volatile int*>());
|
|
static_assert(!CheckCommonWith<T&, int&>());
|
|
static_assert(!CheckCommonWith<T&, const int&>());
|
|
static_assert(!CheckCommonWith<T&, volatile int&>());
|
|
static_assert(!CheckCommonWith<T&, const volatile int&>());
|
|
static_assert(!CheckCommonWith<const T&, int&>());
|
|
static_assert(!CheckCommonWith<volatile T&, int&>());
|
|
static_assert(!CheckCommonWith<const volatile T&, int&>());
|
|
static_assert(!CheckCommonWith<const T&, const int&>());
|
|
static_assert(!CheckCommonWith<const T&, volatile int&>());
|
|
static_assert(!CheckCommonWith<const T&, const volatile int&>());
|
|
static_assert(!CheckCommonWith<const T&, const int&>());
|
|
static_assert(!CheckCommonWith<volatile T&, const int&>());
|
|
static_assert(!CheckCommonWith<const volatile T&, const int&>());
|
|
static_assert(!CheckCommonWith<volatile T&, const int&>());
|
|
static_assert(!CheckCommonWith<volatile T&, volatile int&>());
|
|
static_assert(!CheckCommonWith<volatile T&, const volatile int&>());
|
|
static_assert(!CheckCommonWith<const T&, volatile int&>());
|
|
static_assert(!CheckCommonWith<volatile T&, volatile int&>());
|
|
static_assert(!CheckCommonWith<const volatile T&, volatile int&>());
|
|
static_assert(!CheckCommonWith<const volatile T&, const int&>());
|
|
static_assert(!CheckCommonWith<const volatile T&, volatile int&>());
|
|
static_assert(!CheckCommonWith<const volatile T&, const volatile int&>());
|
|
static_assert(!CheckCommonWith<const T&, const volatile int&>());
|
|
static_assert(!CheckCommonWith<volatile T&, const volatile int&>());
|
|
static_assert(!CheckCommonWith<const volatile T&, const volatile int&>());
|
|
static_assert(!CheckCommonWith<T&, int&&>());
|
|
static_assert(!CheckCommonWith<T&, const int&&>());
|
|
static_assert(!CheckCommonWith<T&, volatile int&&>());
|
|
static_assert(!CheckCommonWith<T&, const volatile int&&>());
|
|
static_assert(!CheckCommonWith<const T&, int&&>());
|
|
static_assert(!CheckCommonWith<volatile T&, int&&>());
|
|
static_assert(!CheckCommonWith<const volatile T&, int&&>());
|
|
static_assert(!CheckCommonWith<const T&, const int&&>());
|
|
static_assert(!CheckCommonWith<const T&, volatile int&&>());
|
|
static_assert(!CheckCommonWith<const T&, const volatile int&&>());
|
|
static_assert(!CheckCommonWith<const T&, const int&&>());
|
|
static_assert(!CheckCommonWith<volatile T&, const int&&>());
|
|
static_assert(!CheckCommonWith<const volatile T&, const int&&>());
|
|
static_assert(!CheckCommonWith<volatile T&, const int&&>());
|
|
static_assert(!CheckCommonWith<volatile T&, volatile int&&>());
|
|
static_assert(!CheckCommonWith<volatile T&, const volatile int&&>());
|
|
static_assert(!CheckCommonWith<const T&, volatile int&&>());
|
|
static_assert(!CheckCommonWith<volatile T&, volatile int&&>());
|
|
static_assert(!CheckCommonWith<const volatile T&, volatile int&&>());
|
|
static_assert(!CheckCommonWith<const volatile T&, const int&&>());
|
|
static_assert(!CheckCommonWith<const volatile T&, volatile int&&>());
|
|
static_assert(!CheckCommonWith<const volatile T&, const volatile int&&>());
|
|
static_assert(!CheckCommonWith<const T&, const volatile int&&>());
|
|
static_assert(!CheckCommonWith<volatile T&, const volatile int&&>());
|
|
static_assert(!CheckCommonWith<const volatile T&, const volatile int&&>());
|
|
static_assert(!CheckCommonWith<T&&, int&>());
|
|
static_assert(!CheckCommonWith<T&&, const int&>());
|
|
static_assert(!CheckCommonWith<T&&, volatile int&>());
|
|
static_assert(!CheckCommonWith<T&&, const volatile int&>());
|
|
static_assert(!CheckCommonWith<const T&&, int&>());
|
|
static_assert(!CheckCommonWith<volatile T&&, int&>());
|
|
static_assert(!CheckCommonWith<const volatile T&&, int&>());
|
|
static_assert(!CheckCommonWith<const T&&, const int&>());
|
|
static_assert(!CheckCommonWith<const T&&, volatile int&>());
|
|
static_assert(!CheckCommonWith<const T&&, const volatile int&>());
|
|
static_assert(!CheckCommonWith<const T&&, const int&>());
|
|
static_assert(!CheckCommonWith<volatile T&&, const int&>());
|
|
static_assert(!CheckCommonWith<const volatile T&&, const int&>());
|
|
static_assert(!CheckCommonWith<volatile T&&, const int&>());
|
|
static_assert(!CheckCommonWith<volatile T&&, volatile int&>());
|
|
static_assert(!CheckCommonWith<volatile T&&, const volatile int&>());
|
|
static_assert(!CheckCommonWith<const T&&, volatile int&>());
|
|
static_assert(!CheckCommonWith<volatile T&&, volatile int&>());
|
|
static_assert(!CheckCommonWith<const volatile T&&, volatile int&>());
|
|
static_assert(!CheckCommonWith<const volatile T&&, const int&>());
|
|
static_assert(!CheckCommonWith<const volatile T&&, volatile int&>());
|
|
static_assert(!CheckCommonWith<const volatile T&&, const volatile int&>());
|
|
static_assert(!CheckCommonWith<const T&&, const volatile int&>());
|
|
static_assert(!CheckCommonWith<volatile T&&, const volatile int&>());
|
|
static_assert(!CheckCommonWith<const volatile T&&, const volatile int&>());
|
|
static_assert(!CheckCommonWith<T&&, int&&>());
|
|
static_assert(!CheckCommonWith<T&&, const int&&>());
|
|
static_assert(!CheckCommonWith<T&&, volatile int&&>());
|
|
static_assert(!CheckCommonWith<T&&, const volatile int&&>());
|
|
static_assert(!CheckCommonWith<const T&&, int&&>());
|
|
static_assert(!CheckCommonWith<volatile T&&, int&&>());
|
|
static_assert(!CheckCommonWith<const volatile T&&, int&&>());
|
|
static_assert(!CheckCommonWith<const T&&, const int&&>());
|
|
static_assert(!CheckCommonWith<const T&&, volatile int&&>());
|
|
static_assert(!CheckCommonWith<const T&&, const volatile int&&>());
|
|
static_assert(!CheckCommonWith<const T&&, const int&&>());
|
|
static_assert(!CheckCommonWith<volatile T&&, const int&&>());
|
|
static_assert(!CheckCommonWith<const volatile T&&, const int&&>());
|
|
static_assert(!CheckCommonWith<volatile T&&, const int&&>());
|
|
static_assert(!CheckCommonWith<volatile T&&, volatile int&&>());
|
|
static_assert(!CheckCommonWith<volatile T&&, const volatile int&&>());
|
|
static_assert(!CheckCommonWith<const T&&, volatile int&&>());
|
|
static_assert(!CheckCommonWith<volatile T&&, volatile int&&>());
|
|
static_assert(!CheckCommonWith<const volatile T&&, volatile int&&>());
|
|
static_assert(!CheckCommonWith<const volatile T&&, const int&&>());
|
|
static_assert(!CheckCommonWith<const volatile T&&, volatile int&&>());
|
|
static_assert(!CheckCommonWith<const volatile T&&, const volatile int&&>());
|
|
static_assert(!CheckCommonWith<const T&&, const volatile int&&>());
|
|
static_assert(!CheckCommonWith<volatile T&&, const volatile int&&>());
|
|
static_assert(!CheckCommonWith<const volatile T&&, const volatile int&&>());
|
|
} // namespace NoDefaultCommonType
|
|
|
|
struct BadBasicCommonType {
|
|
// This test is ill-formed, NDR. If it ever blows up in our faces: that's a good thing.
|
|
// In the meantime, the test should be included. If compiler support is added, then an include guard
|
|
// should be placed so the test doesn't get deleted.
|
|
};
|
|
|
|
namespace std {
|
|
template <>
|
|
struct common_type<BadBasicCommonType, int> {
|
|
using type = BadBasicCommonType;
|
|
};
|
|
|
|
template <>
|
|
struct common_type<int, BadBasicCommonType> {
|
|
using type = int;
|
|
};
|
|
} // namespace std
|
|
static_assert(requires {
|
|
typename std::common_type_t<BadBasicCommonType, int>;
|
|
});
|
|
static_assert(requires {
|
|
typename std::common_type_t<int, BadBasicCommonType>;
|
|
});
|
|
static_assert(!std::same_as<std::common_type_t<BadBasicCommonType, int>,
|
|
std::common_type_t<int, BadBasicCommonType> >);
|
|
static_assert(!CheckCommonWith<BadBasicCommonType, int>());
|
|
|
|
struct DullCommonType {};
|
|
static_assert(!std::convertible_to<DullCommonType, int>);
|
|
|
|
struct T1 {};
|
|
static_assert(!std::convertible_to<DullCommonType, T1>);
|
|
|
|
namespace std {
|
|
template <>
|
|
struct common_type<T1, int> {
|
|
using type = DullCommonType;
|
|
};
|
|
|
|
template <>
|
|
struct common_type<int, T1> {
|
|
using type = DullCommonType;
|
|
};
|
|
} // namespace std
|
|
static_assert(HasValidCommonType<T1, int>());
|
|
static_assert(!CheckCommonWith<T1, int>());
|
|
|
|
struct CommonTypeImplicitlyConstructibleFromInt {
|
|
explicit(false) CommonTypeImplicitlyConstructibleFromInt(int);
|
|
};
|
|
static_assert(requires {
|
|
static_cast<CommonTypeImplicitlyConstructibleFromInt>(0);
|
|
});
|
|
|
|
struct T2 {};
|
|
static_assert(
|
|
!std::convertible_to<CommonTypeImplicitlyConstructibleFromInt, T2>);
|
|
|
|
namespace std {
|
|
template <>
|
|
struct common_type<T2, int> {
|
|
using type = CommonTypeImplicitlyConstructibleFromInt;
|
|
};
|
|
|
|
template <>
|
|
struct common_type<int, T2> {
|
|
using type = CommonTypeImplicitlyConstructibleFromInt;
|
|
};
|
|
} // namespace std
|
|
static_assert(HasValidCommonType<T2, int>());
|
|
static_assert(!CheckCommonWith<T2, int>());
|
|
|
|
struct CommonTypeExplicitlyConstructibleFromInt {
|
|
explicit CommonTypeExplicitlyConstructibleFromInt(int);
|
|
};
|
|
static_assert(requires {
|
|
static_cast<CommonTypeExplicitlyConstructibleFromInt>(0);
|
|
});
|
|
|
|
struct T3 {};
|
|
static_assert(
|
|
!std::convertible_to<CommonTypeExplicitlyConstructibleFromInt, T2>);
|
|
|
|
namespace std {
|
|
template <>
|
|
struct common_type<T3, int> {
|
|
using type = CommonTypeExplicitlyConstructibleFromInt;
|
|
};
|
|
|
|
template <>
|
|
struct common_type<int, T3> {
|
|
using type = CommonTypeExplicitlyConstructibleFromInt;
|
|
};
|
|
} // namespace std
|
|
static_assert(HasValidCommonType<T3, int>());
|
|
static_assert(!CheckCommonWith<T3, int>());
|
|
|
|
struct T4 {};
|
|
struct CommonTypeImplicitlyConstructibleFromT4 {
|
|
explicit(false) CommonTypeImplicitlyConstructibleFromT4(T4);
|
|
};
|
|
static_assert(requires(T4 t4) {
|
|
static_cast<CommonTypeImplicitlyConstructibleFromT4>(t4);
|
|
});
|
|
|
|
namespace std {
|
|
template <>
|
|
struct common_type<T4, int> {
|
|
using type = CommonTypeImplicitlyConstructibleFromT4;
|
|
};
|
|
|
|
template <>
|
|
struct common_type<int, T4> {
|
|
using type = CommonTypeImplicitlyConstructibleFromT4;
|
|
};
|
|
} // namespace std
|
|
static_assert(HasValidCommonType<T4, int>());
|
|
static_assert(!CheckCommonWith<T4, int>());
|
|
|
|
struct T5 {};
|
|
struct CommonTypeExplicitlyConstructibleFromT5 {
|
|
explicit CommonTypeExplicitlyConstructibleFromT5(T5);
|
|
};
|
|
static_assert(requires(T5 t5) {
|
|
static_cast<CommonTypeExplicitlyConstructibleFromT5>(t5);
|
|
});
|
|
|
|
namespace std {
|
|
template <>
|
|
struct common_type<T5, int> {
|
|
using type = CommonTypeExplicitlyConstructibleFromT5;
|
|
};
|
|
|
|
template <>
|
|
struct common_type<int, T5> {
|
|
using type = CommonTypeExplicitlyConstructibleFromT5;
|
|
};
|
|
} // namespace std
|
|
static_assert(HasValidCommonType<T5, int>());
|
|
static_assert(!CheckCommonWith<T5, int>());
|
|
|
|
struct T6 {};
|
|
struct CommonTypeNoCommonReference {
|
|
CommonTypeNoCommonReference(T6);
|
|
CommonTypeNoCommonReference(int);
|
|
};
|
|
|
|
namespace std {
|
|
template <>
|
|
struct common_type<T6, int> {
|
|
using type = CommonTypeNoCommonReference;
|
|
};
|
|
|
|
template <>
|
|
struct common_type<int, T6> {
|
|
using type = CommonTypeNoCommonReference;
|
|
};
|
|
|
|
template <>
|
|
struct common_type<T6&, int&> {};
|
|
|
|
template <>
|
|
struct common_type<int&, T6&> {};
|
|
|
|
template <>
|
|
struct common_type<T6&, const int&> {};
|
|
|
|
template <>
|
|
struct common_type<int&, const T6&> {};
|
|
|
|
template <>
|
|
struct common_type<T6&, volatile int&> {};
|
|
|
|
template <>
|
|
struct common_type<int&, volatile T6&> {};
|
|
|
|
template <>
|
|
struct common_type<T6&, const volatile int&> {};
|
|
|
|
template <>
|
|
struct common_type<int&, const volatile T6&> {};
|
|
|
|
template <>
|
|
struct common_type<const T6&, int&> {};
|
|
|
|
template <>
|
|
struct common_type<const int&, T6&> {};
|
|
|
|
template <>
|
|
struct common_type<const T6&, const int&> {};
|
|
|
|
template <>
|
|
struct common_type<const int&, const T6&> {};
|
|
|
|
template <>
|
|
struct common_type<const T6&, volatile int&> {};
|
|
|
|
template <>
|
|
struct common_type<const int&, volatile T6&> {};
|
|
|
|
template <>
|
|
struct common_type<const T6&, const volatile int&> {};
|
|
|
|
template <>
|
|
struct common_type<const int&, const volatile T6&> {};
|
|
|
|
template <>
|
|
struct common_type<volatile T6&, int&> {};
|
|
|
|
template <>
|
|
struct common_type<volatile int&, T6&> {};
|
|
|
|
template <>
|
|
struct common_type<volatile T6&, const int&> {};
|
|
|
|
template <>
|
|
struct common_type<volatile int&, const T6&> {};
|
|
|
|
template <>
|
|
struct common_type<volatile T6&, volatile int&> {};
|
|
|
|
template <>
|
|
struct common_type<volatile int&, volatile T6&> {};
|
|
|
|
template <>
|
|
struct common_type<volatile T6&, const volatile int&> {};
|
|
|
|
template <>
|
|
struct common_type<volatile int&, const volatile T6&> {};
|
|
|
|
template <>
|
|
struct common_type<const volatile T6&, int&> {};
|
|
|
|
template <>
|
|
struct common_type<const volatile int&, T6&> {};
|
|
|
|
template <>
|
|
struct common_type<const volatile T6&, const int&> {};
|
|
|
|
template <>
|
|
struct common_type<const volatile int&, const T6&> {};
|
|
|
|
template <>
|
|
struct common_type<const volatile T6&, volatile int&> {};
|
|
|
|
template <>
|
|
struct common_type<const volatile int&, volatile T6&> {};
|
|
|
|
template <>
|
|
struct common_type<const volatile T6&, const volatile int&> {};
|
|
|
|
template <>
|
|
struct common_type<const volatile int&, const volatile T6&> {};
|
|
} // namespace std
|
|
|
|
template <typename T, typename U>
|
|
constexpr bool HasCommonReference() noexcept {
|
|
return requires { typename std::common_reference_t<T, U>; };
|
|
}
|
|
|
|
static_assert(HasValidCommonType<T6, int>());
|
|
static_assert(!HasCommonReference<const T6&, const int&>());
|
|
static_assert(!CheckCommonWith<T6, int>());
|
|
|
|
struct T7 {};
|
|
struct CommonTypeNoMetaCommonReference {
|
|
CommonTypeNoMetaCommonReference(T7);
|
|
CommonTypeNoMetaCommonReference(int);
|
|
};
|
|
|
|
namespace std {
|
|
template <>
|
|
struct common_type<T7, int> {
|
|
using type = CommonTypeNoMetaCommonReference;
|
|
};
|
|
|
|
template <>
|
|
struct common_type<int, T7> {
|
|
using type = CommonTypeNoMetaCommonReference;
|
|
};
|
|
|
|
template <>
|
|
struct common_type<T7&, int&> {
|
|
using type = void;
|
|
};
|
|
|
|
template <>
|
|
struct common_type<int&, T7&> {
|
|
using type = void;
|
|
};
|
|
|
|
template <>
|
|
struct common_type<T7&, const int&> {
|
|
using type = void;
|
|
};
|
|
|
|
template <>
|
|
struct common_type<int&, const T7&> {
|
|
using type = void;
|
|
};
|
|
|
|
template <>
|
|
struct common_type<T7&, volatile int&> {
|
|
using type = void;
|
|
};
|
|
|
|
template <>
|
|
struct common_type<int&, volatile T7&> {
|
|
using type = void;
|
|
};
|
|
|
|
template <>
|
|
struct common_type<T7&, const volatile int&> {
|
|
using type = void;
|
|
};
|
|
|
|
template <>
|
|
struct common_type<int&, const volatile T7&> {
|
|
using type = void;
|
|
};
|
|
|
|
template <>
|
|
struct common_type<const T7&, int&> {
|
|
using type = void;
|
|
};
|
|
|
|
template <>
|
|
struct common_type<const int&, T7&> {
|
|
using type = void;
|
|
};
|
|
|
|
template <>
|
|
struct common_type<const T7&, const int&> {
|
|
using type = void;
|
|
};
|
|
|
|
template <>
|
|
struct common_type<const int&, const T7&> {
|
|
using type = void;
|
|
};
|
|
|
|
template <>
|
|
struct common_type<const T7&, volatile int&> {
|
|
using type = void;
|
|
};
|
|
|
|
template <>
|
|
struct common_type<const int&, volatile T7&> {
|
|
using type = void;
|
|
};
|
|
|
|
template <>
|
|
struct common_type<const T7&, const volatile int&> {
|
|
using type = void;
|
|
};
|
|
|
|
template <>
|
|
struct common_type<const int&, const volatile T7&> {
|
|
using type = void;
|
|
};
|
|
|
|
template <>
|
|
struct common_type<volatile T7&, int&> {
|
|
using type = void;
|
|
};
|
|
|
|
template <>
|
|
struct common_type<volatile int&, T7&> {
|
|
using type = void;
|
|
};
|
|
|
|
template <>
|
|
struct common_type<volatile T7&, const int&> {
|
|
using type = void;
|
|
};
|
|
|
|
template <>
|
|
struct common_type<volatile int&, const T7&> {
|
|
using type = void;
|
|
};
|
|
|
|
template <>
|
|
struct common_type<volatile T7&, volatile int&> {
|
|
using type = void;
|
|
};
|
|
|
|
template <>
|
|
struct common_type<volatile int&, volatile T7&> {
|
|
using type = void;
|
|
};
|
|
|
|
template <>
|
|
struct common_type<volatile T7&, const volatile int&> {
|
|
using type = void;
|
|
};
|
|
|
|
template <>
|
|
struct common_type<volatile int&, const volatile T7&> {
|
|
using type = void;
|
|
};
|
|
|
|
template <>
|
|
struct common_type<const volatile T7&, int&> {
|
|
using type = void;
|
|
};
|
|
|
|
template <>
|
|
struct common_type<const volatile int&, T7&> {
|
|
using type = void;
|
|
};
|
|
|
|
template <>
|
|
struct common_type<const volatile T7&, const int&> {
|
|
using type = void;
|
|
};
|
|
|
|
template <>
|
|
struct common_type<const volatile int&, const T7&> {
|
|
using type = void;
|
|
};
|
|
|
|
template <>
|
|
struct common_type<const volatile T7&, volatile int&> {
|
|
using type = void;
|
|
};
|
|
|
|
template <>
|
|
struct common_type<const volatile int&, volatile T7&> {
|
|
using type = void;
|
|
};
|
|
|
|
template <>
|
|
struct common_type<const volatile T7&, const volatile int&> {
|
|
using type = void;
|
|
};
|
|
|
|
template <>
|
|
struct common_type<const volatile int&, const volatile T7&> {
|
|
using type = void;
|
|
};
|
|
} // namespace std
|
|
static_assert(HasValidCommonType<T7, int>());
|
|
static_assert(HasValidCommonType<const T7&, const int&>());
|
|
static_assert(HasCommonReference<const T7&, const int&>());
|
|
static_assert(
|
|
!HasCommonReference<std::common_type_t<T7, int>&,
|
|
std::common_reference_t<const T7&, const int&> >());
|
|
static_assert(!CheckCommonWith<T7, int>());
|
|
|
|
struct CommonWithInt {
|
|
operator int() const volatile;
|
|
};
|
|
|
|
namespace std {
|
|
template <>
|
|
struct common_type<CommonWithInt, int> {
|
|
using type = int;
|
|
};
|
|
|
|
template <>
|
|
struct common_type<int, CommonWithInt> : common_type<CommonWithInt, int> {};
|
|
|
|
template <>
|
|
struct common_type<CommonWithInt&, int&> : common_type<CommonWithInt, int> {};
|
|
|
|
template <>
|
|
struct common_type<int&, CommonWithInt&> : common_type<CommonWithInt, int> {};
|
|
|
|
template <>
|
|
struct common_type<CommonWithInt&, const int&>
|
|
: common_type<CommonWithInt, int> {};
|
|
|
|
template <>
|
|
struct common_type<int&, const CommonWithInt&>
|
|
: common_type<CommonWithInt, int> {};
|
|
|
|
template <>
|
|
struct common_type<CommonWithInt&, volatile int&>
|
|
: common_type<CommonWithInt, int> {};
|
|
|
|
template <>
|
|
struct common_type<int&, volatile CommonWithInt&>
|
|
: common_type<CommonWithInt, int> {};
|
|
|
|
template <>
|
|
struct common_type<CommonWithInt&, const volatile int&>
|
|
: common_type<CommonWithInt, int> {};
|
|
|
|
template <>
|
|
struct common_type<int&, const volatile CommonWithInt&>
|
|
: common_type<CommonWithInt, int> {};
|
|
|
|
template <>
|
|
struct common_type<const CommonWithInt&, int&>
|
|
: common_type<CommonWithInt, int> {};
|
|
|
|
template <>
|
|
struct common_type<const int&, CommonWithInt&>
|
|
: common_type<CommonWithInt, int> {};
|
|
|
|
template <>
|
|
struct common_type<const CommonWithInt&, const int&>
|
|
: common_type<CommonWithInt, int> {};
|
|
|
|
template <>
|
|
struct common_type<const int&, const CommonWithInt&>
|
|
: common_type<CommonWithInt, int> {};
|
|
|
|
template <>
|
|
struct common_type<const CommonWithInt&, volatile int&>
|
|
: common_type<CommonWithInt, int> {};
|
|
|
|
template <>
|
|
struct common_type<const int&, volatile CommonWithInt&>
|
|
: common_type<CommonWithInt, int> {};
|
|
|
|
template <>
|
|
struct common_type<const CommonWithInt&, const volatile int&>
|
|
: common_type<CommonWithInt, int> {};
|
|
|
|
template <>
|
|
struct common_type<const int&, const volatile CommonWithInt&>
|
|
: common_type<CommonWithInt, int> {};
|
|
|
|
template <>
|
|
struct common_type<volatile CommonWithInt&, int&>
|
|
: common_type<CommonWithInt, int> {};
|
|
|
|
template <>
|
|
struct common_type<volatile int&, CommonWithInt&>
|
|
: common_type<CommonWithInt, int> {};
|
|
|
|
template <>
|
|
struct common_type<volatile CommonWithInt&, const int&>
|
|
: common_type<CommonWithInt, int> {};
|
|
|
|
template <>
|
|
struct common_type<volatile int&, const CommonWithInt&>
|
|
: common_type<CommonWithInt, int> {};
|
|
|
|
template <>
|
|
struct common_type<volatile CommonWithInt&, volatile int&>
|
|
: common_type<CommonWithInt, int> {};
|
|
|
|
template <>
|
|
struct common_type<volatile int&, volatile CommonWithInt&>
|
|
: common_type<CommonWithInt, int> {};
|
|
|
|
template <>
|
|
struct common_type<volatile CommonWithInt&, const volatile int&>
|
|
: common_type<CommonWithInt, int> {};
|
|
|
|
template <>
|
|
struct common_type<volatile int&, const volatile CommonWithInt&>
|
|
: common_type<CommonWithInt, int> {};
|
|
|
|
template <>
|
|
struct common_type<const volatile CommonWithInt&, int&>
|
|
: common_type<CommonWithInt, int> {};
|
|
|
|
template <>
|
|
struct common_type<const volatile int&, CommonWithInt&>
|
|
: common_type<CommonWithInt, int> {};
|
|
|
|
template <>
|
|
struct common_type<const volatile CommonWithInt&, const int&>
|
|
: common_type<CommonWithInt, int> {};
|
|
|
|
template <>
|
|
struct common_type<const volatile int&, const CommonWithInt&>
|
|
: common_type<CommonWithInt, int> {};
|
|
|
|
template <>
|
|
struct common_type<const volatile CommonWithInt&, volatile int&>
|
|
: common_type<CommonWithInt, int> {};
|
|
|
|
template <>
|
|
struct common_type<const volatile int&, volatile CommonWithInt&>
|
|
: common_type<CommonWithInt, int> {};
|
|
|
|
template <>
|
|
struct common_type<const volatile CommonWithInt&, const volatile int&>
|
|
: common_type<CommonWithInt, int> {};
|
|
|
|
template <>
|
|
struct common_type<const volatile int&, const volatile CommonWithInt&>
|
|
: common_type<CommonWithInt, int> {};
|
|
} // namespace std
|
|
static_assert(CheckCommonWith<CommonWithInt, int>());
|
|
|
|
struct CommonWithIntButRefLong {
|
|
operator int() const volatile;
|
|
};
|
|
|
|
namespace std {
|
|
template <>
|
|
struct common_type<CommonWithIntButRefLong, int> {
|
|
using type = int;
|
|
};
|
|
|
|
template <>
|
|
struct common_type<int, CommonWithIntButRefLong>
|
|
: common_type<CommonWithIntButRefLong, int> {};
|
|
|
|
template <>
|
|
struct common_type<CommonWithIntButRefLong&, int&> {
|
|
using type = long;
|
|
};
|
|
|
|
template <>
|
|
struct common_type<int&, CommonWithIntButRefLong&>
|
|
: common_type<CommonWithIntButRefLong&, int&> {};
|
|
|
|
template <>
|
|
struct common_type<CommonWithIntButRefLong&, const int&>
|
|
: common_type<CommonWithIntButRefLong&, int&> {};
|
|
|
|
template <>
|
|
struct common_type<int&, const CommonWithIntButRefLong&>
|
|
: common_type<CommonWithIntButRefLong&, int&> {};
|
|
|
|
template <>
|
|
struct common_type<CommonWithIntButRefLong&, volatile int&>
|
|
: common_type<CommonWithIntButRefLong&, int&> {};
|
|
|
|
template <>
|
|
struct common_type<int&, volatile CommonWithIntButRefLong&>
|
|
: common_type<CommonWithIntButRefLong&, int&> {};
|
|
|
|
template <>
|
|
struct common_type<CommonWithIntButRefLong&, const volatile int&>
|
|
: common_type<CommonWithIntButRefLong&, int&> {};
|
|
|
|
template <>
|
|
struct common_type<int&, const volatile CommonWithIntButRefLong&>
|
|
: common_type<CommonWithIntButRefLong&, int&> {};
|
|
|
|
template <>
|
|
struct common_type<const CommonWithIntButRefLong&, int&>
|
|
: common_type<CommonWithIntButRefLong&, int&> {};
|
|
|
|
template <>
|
|
struct common_type<const int&, CommonWithIntButRefLong&>
|
|
: common_type<CommonWithIntButRefLong&, int&> {};
|
|
|
|
template <>
|
|
struct common_type<const CommonWithIntButRefLong&, const int&>
|
|
: common_type<CommonWithIntButRefLong&, int&> {};
|
|
|
|
template <>
|
|
struct common_type<const int&, const CommonWithIntButRefLong&>
|
|
: common_type<CommonWithIntButRefLong&, int&> {};
|
|
|
|
template <>
|
|
struct common_type<const CommonWithIntButRefLong&, volatile int&>
|
|
: common_type<CommonWithIntButRefLong&, int&> {};
|
|
|
|
template <>
|
|
struct common_type<const int&, volatile CommonWithIntButRefLong&>
|
|
: common_type<CommonWithIntButRefLong&, int&> {};
|
|
|
|
template <>
|
|
struct common_type<const CommonWithIntButRefLong&, const volatile int&>
|
|
: common_type<CommonWithIntButRefLong&, int&> {};
|
|
|
|
template <>
|
|
struct common_type<const int&, const volatile CommonWithIntButRefLong&>
|
|
: common_type<CommonWithIntButRefLong&, int&> {};
|
|
|
|
template <>
|
|
struct common_type<volatile CommonWithIntButRefLong&, int&>
|
|
: common_type<CommonWithIntButRefLong&, int&> {};
|
|
|
|
template <>
|
|
struct common_type<volatile int&, CommonWithIntButRefLong&>
|
|
: common_type<CommonWithIntButRefLong&, int&> {};
|
|
|
|
template <>
|
|
struct common_type<volatile CommonWithIntButRefLong&, const int&>
|
|
: common_type<CommonWithIntButRefLong&, int&> {};
|
|
|
|
template <>
|
|
struct common_type<volatile int&, const CommonWithIntButRefLong&>
|
|
: common_type<CommonWithIntButRefLong&, int&> {};
|
|
|
|
template <>
|
|
struct common_type<volatile CommonWithIntButRefLong&, volatile int&>
|
|
: common_type<CommonWithIntButRefLong&, int&> {};
|
|
|
|
template <>
|
|
struct common_type<volatile int&, volatile CommonWithIntButRefLong&>
|
|
: common_type<CommonWithIntButRefLong&, int&> {};
|
|
|
|
template <>
|
|
struct common_type<volatile CommonWithIntButRefLong&, const volatile int&>
|
|
: common_type<CommonWithIntButRefLong&, int&> {};
|
|
|
|
template <>
|
|
struct common_type<volatile int&, const volatile CommonWithIntButRefLong&>
|
|
: common_type<CommonWithIntButRefLong&, int&> {};
|
|
|
|
template <>
|
|
struct common_type<const volatile CommonWithIntButRefLong&, int&>
|
|
: common_type<CommonWithIntButRefLong&, int&> {};
|
|
|
|
template <>
|
|
struct common_type<const volatile int&, CommonWithIntButRefLong&>
|
|
: common_type<CommonWithIntButRefLong&, int&> {};
|
|
|
|
template <>
|
|
struct common_type<const volatile CommonWithIntButRefLong&, const int&>
|
|
: common_type<CommonWithIntButRefLong&, int&> {};
|
|
|
|
template <>
|
|
struct common_type<const volatile int&, const CommonWithIntButRefLong&>
|
|
: common_type<CommonWithIntButRefLong&, int&> {};
|
|
|
|
template <>
|
|
struct common_type<const volatile CommonWithIntButRefLong&, volatile int&>
|
|
: common_type<CommonWithIntButRefLong&, int&> {};
|
|
|
|
template <>
|
|
struct common_type<const volatile int&, volatile CommonWithIntButRefLong&>
|
|
: common_type<CommonWithIntButRefLong&, int&> {};
|
|
|
|
template <>
|
|
struct common_type<const volatile CommonWithIntButRefLong&, const volatile int&>
|
|
: common_type<CommonWithIntButRefLong&, int&> {};
|
|
|
|
template <>
|
|
struct common_type<const volatile int&, const volatile CommonWithIntButRefLong&>
|
|
: common_type<CommonWithIntButRefLong&, int&> {};
|
|
} // namespace std
|
|
static_assert(CheckCommonWith<CommonWithIntButRefLong, int>());
|