blob: 9acbc66d9180465ed365d831dd990c7d7915ad69 [file] [log] [blame]
// { dg-do compile { target c++11 } }
// Copyright (C) 2012-2023 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License along
// with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
#include <type_traits>
#include <initializer_list>
// Helper types:
struct has_type_impl
{
template<typename T, typename = typename T::type>
static std::true_type test(int);
template<typename>
static std::false_type test(...);
};
template<typename T>
struct has_type : public decltype(has_type_impl::test<T>(0))
{};
template<typename T, typename Expected>
struct is_expected_type : public std::is_same<typename T::type, Expected>
{};
template<typename P1, typename P2>
struct and_ : public std::conditional<P1::value, P2, std::false_type>::type
{};
template<typename T, typename Expected>
struct is_type : public and_<has_type<T>, is_expected_type<T, Expected>>
{};
// Inspection types:
struct S {};
struct B {};
struct D : B {};
struct F1 { operator void*(); };
struct F2 { operator void*(); };
struct G1 { operator const void*(); };
struct G2 { operator volatile void*(); };
template<typename T>
struct ImplicitTo
{
operator T();
};
template<typename T>
struct ExplicitTo
{
explicit operator T();
};
template<typename T>
struct PrivateImplicitTo
{
private:
operator T();
};
auto lmd1 = [](int, double) {};
auto lmd2 = [](int, double) {};
struct Abstract
{
virtual ~Abstract() = 0;
};
enum class ScEn;
enum UnscEn : int;
struct Ukn;
union U
{
int i;
};
union U2
{
long i;
};
union UConv1
{
operator Abstract*();
};
union UConv2
{
operator Abstract*();
};
struct X1 {};
struct X2 {};
struct RX12 {};
struct RX21 {};
struct Y1 {};
struct Y2 {};
struct Y3 {};
struct Y4 {};
namespace std {
template<>
struct common_type<X1, X2>
{
typedef RX12 type;
};
template<>
struct common_type<X2, X1>
{
typedef RX21 type;
};
template<>
struct common_type<RX12, X1>
{
typedef Y1 type;
};
template<>
struct common_type<X1, RX12>
{
typedef Y2 type;
};
template<>
struct common_type<RX21, X1>
{
typedef Y3 type;
};
template<>
struct common_type<X1, RX21>
{
typedef Y4 type;
};
}
static_assert(is_type<std::common_type<int>, int>(), "");
static_assert(is_type<std::common_type<const int>, int>(), "");
static_assert(is_type<std::common_type<int, int>, int>(), "");
static_assert(is_type<std::common_type<const int, int>, int>(), "");
static_assert(is_type<std::common_type<ScEn, ScEn>, ScEn>(), "");
static_assert(is_type<std::common_type<UnscEn, UnscEn>, UnscEn>(), "");
static_assert(is_type<std::common_type<UnscEn, int>, int>(), "");
static_assert(is_type<std::common_type<int, int, int>, int>(), "");
static_assert(is_type<std::common_type<int, int, int, int>, int>(), "");
static_assert(is_type<std::common_type<int, int, int, int, int>, int>(), "");
static_assert(is_type<std::common_type<S, S>, S>(), "");
static_assert(is_type<std::common_type<const S, const S>, S>(), "");
static_assert(is_type<std::common_type<std::initializer_list<int>,
std::initializer_list<int>>, std::initializer_list<int>>(), "");
static_assert(is_type<std::common_type<B, D>, B>(), "");
static_assert(is_type<std::common_type<D, B>, B>(), "");
static_assert(is_type<std::common_type<F1, F2>, void*>(), "");
static_assert(is_type<std::common_type<F2, F1>, void*>(), "");
static_assert(is_type<std::common_type<G1, G2>, const volatile void*>(), "");
static_assert(is_type<std::common_type<G2, G1>, const volatile void*>(), "");
static_assert(is_type<std::common_type<int*, const volatile int*>,
const volatile int*>(), "");
static_assert(is_type<std::common_type<void*, const volatile int*>,
const volatile void*>(), "");
static_assert(is_type<std::common_type<void>, void>(), "");
static_assert(is_type<std::common_type<const void>, void>(), "");
static_assert(is_type<std::common_type<void, void>, void>(), "");
static_assert(is_type<std::common_type<const void, const void>, void>(), "");
static_assert(is_type<std::common_type<int&, int&&>, int>(), "");
static_assert(is_type<std::common_type<int&, int&>, int>(), "");
static_assert(is_type<std::common_type<int&&, int&&>, int>(), "");
static_assert(is_type<std::common_type<int&&, const int&&>, int>(), "");
static_assert(is_type<std::common_type<U&, const U&&>, U>(), "");
static_assert(is_type<std::common_type<U&, U&>, U>(), "");
static_assert(is_type<std::common_type<U&&, U&&>, U>(), "");
static_assert(is_type<std::common_type<int B::*, int D::*>, int D::*>(), "");
static_assert(is_type<std::common_type<int D::*, int B::*>, int D::*>(), "");
static_assert(is_type<std::common_type<const int B::*, volatile int D::*>,
const volatile int D::*>(), "");
static_assert(is_type<std::common_type<int (B::*)(), int (D::*)()>,
int (D::*)()>(), "");
static_assert(is_type<std::common_type<int (B::*)() const, int (D::*)() const>,
int (D::*)() const>(), "");
static_assert(is_type<std::common_type<int[3], int[3]>, int*>(), "");
static_assert(is_type<std::common_type<int[1], const int[3]>,
const int*>(), "");
static_assert(is_type<std::common_type<void(), void()>, void(*)()>(), "");
static_assert(is_type<std::common_type<void(&)(), void(&)()>, void(*)()>(), "");
static_assert(is_type<std::common_type<void(&)(), void(&&)()>,
void(*)()>(), "");
static_assert(is_type<std::common_type<void(&&)(), void(&)()>,
void(*)()>(), "");
static_assert(is_type<std::common_type<void(&&)(), void(&&)()>,
void(*)()>(), "");
static_assert(is_type<std::common_type<ImplicitTo<int>, int>, int>(), "");
static_assert(is_type<std::common_type<const ImplicitTo<int>, int>, int>(), "");
static_assert(is_type<std::common_type<ImplicitTo<int>, ImplicitTo<int>>,
ImplicitTo<int>>(), "");
static_assert(is_type<std::common_type<ImplicitTo<int>, int,
ImplicitTo<int>>, int>(), "");
static_assert(is_type<std::common_type<ExplicitTo<int>, ExplicitTo<int>>,
ExplicitTo<int>>(), "");
static_assert(is_type<std::common_type<decltype(lmd1), decltype(lmd1)>,
decltype(lmd1)>(), "");
static_assert(is_type<std::common_type<decltype(lmd1)&, decltype(lmd1)&>,
decltype(lmd1)>(), "");
static_assert(is_type<std::common_type<decltype(lmd1)&, decltype(lmd2)&>,
void(*)(int, double)>(), "");
static_assert(is_type<std::common_type<decltype(nullptr), void*>, void*>(), "");
static_assert(is_type<std::common_type<decltype(nullptr), int*>, int*>(), "");
static_assert(is_type<std::common_type<const decltype(nullptr)&, int*>,
int*>(), "");
static_assert(is_type<std::common_type<decltype(nullptr), const volatile int*>,
const volatile int*>(), "");
static_assert(is_type<std::common_type<decltype(nullptr), int (B::*)()>,
int (B::*)()>(), "");
static_assert(is_type<std::common_type<decltype(nullptr), int (B::*)() const>,
int (B::*)() const>(), "");
static_assert(is_type<std::common_type<decltype(nullptr), const int B::*>,
const int B::*>(), "");
static_assert(is_type<std::common_type<Abstract&, Abstract&>, Abstract>(), "");
static_assert(is_type<std::common_type<Ukn&, Ukn&>, Ukn>(), "");
static_assert(is_type<std::common_type<ImplicitTo<B&>, B&>, B>(), "");
static_assert(is_type<std::common_type<ImplicitTo<B&>&, B&&>, B>(), "");
static_assert(is_type<std::common_type<UConv1, const Abstract*&>,
const Abstract*>(), "");
static_assert(is_type<std::common_type<UConv1, UConv2>, Abstract*>(), "");
static_assert(is_type<std::common_type<UConv1&, UConv2&>, Abstract*>(), "");
static_assert(is_type<std::common_type<Abstract&&, Abstract&&>,
Abstract>(), "");
static_assert(is_type<std::common_type<const Abstract&&,
const Abstract&&>, Abstract>(), "");
static_assert(is_type<std::common_type<volatile Abstract&&,
volatile Abstract&&>, Abstract>(), "");
static_assert(is_type<std::common_type<Ukn&&, Ukn&&>, Ukn>(), "");
static_assert(is_type<std::common_type<const Ukn&&, const Ukn&&>,
Ukn>(), "");
static_assert(is_type<std::common_type<volatile Ukn&&, volatile Ukn&&>,
Ukn>(), "");
static_assert(is_type<std::common_type<X1, X2>, RX12>(), "");
static_assert(is_type<std::common_type<const X1, X2>, RX12>(), "");
static_assert(is_type<std::common_type<X1&, const X2>, RX12>(), "");
static_assert(is_type<std::common_type<const X1&, const X2&>, RX12>(), "");
static_assert(is_type<std::common_type<X2, X1>, RX21>(), "");
static_assert(is_type<std::common_type<X1, X2, X1>, Y1>(), "");
static_assert(is_type<std::common_type<X2, X1, X1>, Y3>(), "");
static_assert(is_type<std::common_type<X1, X1, X2>, RX12>(), "");
static_assert(is_type<std::common_type<X1&, const X1, const X2&&>, RX12>(), "");
static_assert(is_type<std::common_type<X1, X1, X2, X1>, Y1>(), "");
static_assert(!has_type<std::common_type<>>(), "");
static_assert(!has_type<std::common_type<int, S>>(), "");
static_assert(!has_type<std::common_type<U, S>>(), "");
static_assert(!has_type<std::common_type<U, U2>>(), "");
static_assert(!has_type<std::common_type<PrivateImplicitTo<int>, int>>(), "");
static_assert(!has_type<std::common_type<const PrivateImplicitTo<int>,
int>>(), "");
static_assert(!has_type<std::common_type<int, Ukn>>(), "");
static_assert(!has_type<std::common_type<int, Abstract>>(), "");
static_assert(!has_type<std::common_type<Ukn, Abstract>>(), "");
static_assert(!has_type<std::common_type<int, void>>(), "");
static_assert(!has_type<std::common_type<int, const volatile void>>(), "");
static_assert(!has_type<std::common_type<Abstract, void>>(), "");
static_assert(!has_type<std::common_type<Ukn, void>>(), "");
static_assert(!has_type<std::common_type<int[4], void>>(), "");
static_assert(!has_type<std::common_type<ScEn, void>>(), "");
static_assert(!has_type<std::common_type<UnscEn, void>>(), "");
static_assert(!has_type<std::common_type<U, void>>(), "");
static_assert(!has_type<std::common_type<std::initializer_list<int>,
void>>(), "");
static_assert(!has_type<std::common_type<int, int, int, S>>(), "");
static_assert(!has_type<std::common_type<int, int, S, int>>(), "");
static_assert(!has_type<std::common_type<int, S, int, int>>(), "");
static_assert(!has_type<std::common_type<S, int, int, int>>(), "");
static_assert(!has_type<std::common_type<int, int, void, int, int>>(), "");
static_assert(!has_type<std::common_type<B, S>>(), "");
static_assert(!has_type<std::common_type<int, B, S>>(), "");
static_assert(!has_type<std::common_type<B, int, S>>(), "");
static_assert(!has_type<std::common_type<B, S, int>>(), "");
static_assert(!has_type<std::common_type<int*, double*>>(), "");
static_assert(!has_type<std::common_type<void*, void(*)(...)>>(), "");
static_assert(!has_type<std::common_type<void(*)(), void(*)(...)>>(), "");
static_assert(!has_type<std::common_type<void(*)(), void(S::*)()>>(), "");
static_assert(!has_type<std::common_type<void(S::*)() const,
void(S::*)()>>(), "");
static_assert(!has_type<std::common_type<int S::*, long S::*>>(), "");
static_assert(!has_type<std::common_type<int S::*, void(S::*)()>>(), "");
static_assert(!has_type<std::common_type<int (B::*)(),
int (D::*)() const>>(), "");
static_assert(!has_type<std::common_type<int (B::*)() const,
int (D::*)()>>(), "");
static_assert(!has_type<std::common_type<int, ExplicitTo<int>>>(), "");
static_assert(!has_type<std::common_type<ImplicitTo<int>,
ExplicitTo<int>>>(), "");
static_assert(!has_type<std::common_type<ScEn, int>>(), "");
static_assert(!has_type<std::common_type<ScEn, UnscEn>>(), "");
static_assert(!has_type<std::common_type<U, S, Abstract, void, D,
int (B::*)(), int[5]>>(), "");
static_assert(!has_type<std::common_type<UConv1, Abstract&&>>(), "");
static_assert(!has_type<std::common_type<std::initializer_list<int>,
std::initializer_list<long>>>(), "");
// PR libstdc++/89102
static_assert(!has_type<std::common_type<int() &>>(), "");
static_assert(!has_type<std::common_type<int() & noexcept>>(), "");
static_assert(!has_type<std::common_type<int() const>>(), "");
static_assert(!has_type<std::common_type<int(...) &>>(), "");
static_assert(!has_type<std::common_type<int(...) & noexcept>>(), "");
static_assert(!has_type<std::common_type<int(...) const>>(), "");
void test(int i)
{
auto local_lmd1 = [=](int, double) { return i + i; };
auto local_lmd2 = [=](int, double) { return i - i; };
static_assert(is_type<std::common_type<decltype(local_lmd1),
decltype(local_lmd1)>, decltype(local_lmd1)>(), "");
static_assert(is_type<std::common_type<decltype(local_lmd1)&,
decltype(local_lmd1)>, decltype(local_lmd1)>(), "");
static_assert(is_type<std::common_type<decltype(local_lmd1)&,
decltype(local_lmd1)&>, decltype(local_lmd1)>(), "");
static_assert(!has_type<std::common_type<decltype(local_lmd1),
decltype(lmd1)>>(), "");
static_assert(!has_type<std::common_type<decltype(local_lmd1)&,
decltype(lmd1)&>>(), "");
static_assert(!has_type<std::common_type<decltype(local_lmd1),
decltype(local_lmd2)>>(), "");
static_assert(!has_type<std::common_type<decltype(local_lmd1)&,
decltype(local_lmd2)&>>(), "");
}