diff --git a/libcxx/include/concepts b/libcxx/include/concepts --- a/libcxx/include/concepts +++ b/libcxx/include/concepts @@ -180,6 +180,23 @@ convertible_to<_Tp, common_reference_t<_Tp, _Up>> && convertible_to<_Up, common_reference_t<_Tp, _Up>>; +// [concept.common] +template +concept common_with = + same_as, common_type_t<_Up, _Tp>> && + requires { + static_cast>(_VSTD::declval<_Tp>()); + static_cast>(_VSTD::declval<_Up>()); + } && + common_reference_with< + add_lvalue_reference_t, + add_lvalue_reference_t> && + common_reference_with< + add_lvalue_reference_t>, + common_reference_t< + add_lvalue_reference_t, + add_lvalue_reference_t>>; + // [concepts.arithmetic], arithmetic concepts template concept integral = is_integral_v<_Tp>; diff --git a/libcxx/test/std/concepts/lang/common.compile.pass.cpp b/libcxx/test/std/concepts/lang/common.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/concepts/lang/common.compile.pass.cpp @@ -0,0 +1,509 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// UNSUPPORTED: libcpp-no-concepts + +// template +// concept common_with; + +#include + +template +constexpr bool CheckCommonWith() noexcept { + static_assert(std::common_with); + static_assert(std::common_with); + static_assert(std::common_with); + static_assert(std::common_with); + static_assert(std::common_with); + static_assert(std::common_with); + static_assert(std::common_with); + static_assert(std::common_with); + static_assert(std::common_with); + static_assert(std::common_with); + static_assert(std::common_with); + static_assert(std::common_with); + static_assert(std::common_with); + static_assert(std::common_with); + static_assert(std::common_with); + static_assert(std::common_with); + static_assert(std::common_with); + static_assert(std::common_with); + static_assert(std::common_with); + static_assert(std::common_with); + static_assert(std::common_with); + static_assert(std::common_with); + static_assert(std::common_with); + static_assert(std::common_with); + + return std::common_with; +} + +template +constexpr bool HasValidCommonType() noexcept { + return requires { typename std::common_type_t; } + &&std::same_as, std::common_type_t >; +} + +namespace BuiltinTypes { +// fundamental types +static_assert(std::common_with); +static_assert(CheckCommonWith()); +static_assert(CheckCommonWith()); +static_assert(CheckCommonWith()); +#ifndef _LIBCPP_HAS_NO_INT128 +static_assert(CheckCommonWith()); +#endif +static_assert(CheckCommonWith()); + +// arrays +static_assert(CheckCommonWith()); + +// pointers +static_assert(CheckCommonWith()); +static_assert(CheckCommonWith()); +static_assert(CheckCommonWith()); +static_assert(CheckCommonWith()); +static_assert(CheckCommonWith()); +static_assert(CheckCommonWith()); +static_assert(CheckCommonWith()); +static_assert(CheckCommonWith()); +static_assert(CheckCommonWith()); +static_assert(CheckCommonWith()); +static_assert(CheckCommonWith()); +static_assert(CheckCommonWith()); +static_assert(CheckCommonWith()); + +static_assert(CheckCommonWith()); +static_assert(CheckCommonWith()); +static_assert(CheckCommonWith()); +static_assert(CheckCommonWith()); +static_assert(CheckCommonWith()); +static_assert(CheckCommonWith()); + +struct S {}; +static_assert(CheckCommonWith()); +static_assert(CheckCommonWith()); +static_assert(CheckCommonWith()); +static_assert(CheckCommonWith()); +static_assert(CheckCommonWith()); +static_assert( + CheckCommonWith()); +static_assert(CheckCommonWith()); +static_assert( + CheckCommonWith()); +static_assert(CheckCommonWith()); +static_assert(CheckCommonWith()); + +// nonsense +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert( + !std::common_with); +static_assert( + !std::common_with); +} // namespace BuiltinTypes + +namespace NoDefaultCommonType { +class T {}; + +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +static_assert(!std::common_with); +} // 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 { + using type = BadBasicCommonType; +}; + +template <> +struct common_type { + using type = int; +}; +} // namespace std +static_assert(requires { + typename std::common_type_t; +}); +static_assert(requires { + typename std::common_type_t; +}); +static_assert(!std::same_as, + std::common_type_t >); +static_assert(!std::common_with); + +struct DullCommonType {}; +static_assert(!std::convertible_to); + +struct T1 {}; +static_assert(!std::convertible_to); + +namespace std { +template <> +struct common_type { + using type = DullCommonType; +}; + +template <> +struct common_type { + using type = DullCommonType; +}; +} // namespace std +static_assert(HasValidCommonType()); +static_assert(!std::common_with); + +struct CommonTypeImplicitlyConstructibleFromInt { + explicit(false) CommonTypeImplicitlyConstructibleFromInt(int); +}; +static_assert(requires { + static_cast(0); +}); + +struct T2 {}; +static_assert( + !std::convertible_to); + +namespace std { +template <> +struct common_type { + using type = CommonTypeImplicitlyConstructibleFromInt; +}; + +template <> +struct common_type { + using type = CommonTypeImplicitlyConstructibleFromInt; +}; +} // namespace std +static_assert(HasValidCommonType()); +static_assert(!std::common_with); + +struct CommonTypeExplicitlyConstructibleFromInt { + explicit CommonTypeExplicitlyConstructibleFromInt(int); +}; +static_assert(requires { + static_cast(0); +}); + +struct T3 {}; +static_assert( + !std::convertible_to); + +namespace std { +template <> +struct common_type { + using type = CommonTypeExplicitlyConstructibleFromInt; +}; + +template <> +struct common_type { + using type = CommonTypeExplicitlyConstructibleFromInt; +}; +} // namespace std +static_assert(HasValidCommonType()); +static_assert(!std::common_with); + +struct T4 {}; +struct CommonTypeImplicitlyConstructibleFromT4 { + explicit(false) CommonTypeImplicitlyConstructibleFromT4(T4); +}; +static_assert(requires(T4 t4) { + static_cast(t4); +}); + +namespace std { +template <> +struct common_type { + using type = CommonTypeImplicitlyConstructibleFromT4; +}; + +template <> +struct common_type { + using type = CommonTypeImplicitlyConstructibleFromT4; +}; +} // namespace std +static_assert(HasValidCommonType()); +static_assert(!std::common_with); + +struct T5 {}; +struct CommonTypeExplicitlyConstructibleFromT5 { + explicit CommonTypeExplicitlyConstructibleFromT5(T5); +}; +static_assert(requires(T5 t5) { + static_cast(t5); +}); + +namespace std { +template <> +struct common_type { + using type = CommonTypeExplicitlyConstructibleFromT5; +}; + +template <> +struct common_type { + using type = CommonTypeExplicitlyConstructibleFromT5; +}; +} // namespace std +static_assert(HasValidCommonType()); +static_assert(!std::common_with); + +struct T6 {}; +struct CommonTypeNoCommonReference { + CommonTypeNoCommonReference(T6); + CommonTypeNoCommonReference(int); +}; + +namespace std { +template <> +struct common_type { + using type = CommonTypeNoCommonReference; +}; + +template <> +struct common_type { + using type = CommonTypeNoCommonReference; +}; + +template <> +struct common_type {}; + +template <> +struct common_type {}; +} // namespace std + +template +constexpr bool HasCommonReference() noexcept { + return requires { typename std::common_reference_t; }; +} + +static_assert(HasValidCommonType()); +static_assert(!HasCommonReference()); +static_assert(!std::common_with); + +struct T7 {}; +struct CommonTypeNoMetaCommonReference { + CommonTypeNoMetaCommonReference(T7); + CommonTypeNoMetaCommonReference(int); +}; + +namespace std { +template <> +struct common_type { + using type = CommonTypeNoMetaCommonReference; +}; + +template <> +struct common_type { + using type = CommonTypeNoMetaCommonReference; +}; + +template <> +struct common_type { + using type = void; +}; + +template <> +struct common_type { + using type = void; +}; +} // namespace std +static_assert(HasValidCommonType()); +static_assert(HasValidCommonType()); +static_assert(HasCommonReference()); +static_assert( + !HasCommonReference&, + std::common_reference_t >()); +static_assert(!std::common_with); + +struct T8 { + operator int() const; +}; + +namespace std { +template <> +struct common_type { + using type = int; +}; + +template <> +struct common_type { + using type = int; +}; +} // namespace std +static_assert(std::common_with); + +struct T9 { + operator int() const; +}; + +namespace std { +template <> +struct common_type { + using type = int; +}; + +template <> +struct common_type { + using type = int; +}; + +template <> +struct common_type { + using type = long; +}; + +template <> +struct common_type { + using type = long; +}; +} // namespace std +static_assert(std::common_with); + +int main(int, char**) { return 0; }