forked from OSchip/llvm-project
[libcxx] adds concepts std::equality_comparable[_with]
Implements parts of: - P0898R3 Standard Library Concepts - P1754 Rename concepts to standard_case for C++20, while we still can Depends on D96660 Reviewed By: ldionne, #libc, Quuxplusone Differential Revision: https://reviews.llvm.org/D97176
This commit is contained in:
parent
87bbf3d1f8
commit
e63ddcccf8
|
@ -243,6 +243,38 @@ template<class _Tp>
|
|||
concept move_constructible =
|
||||
constructible_from<_Tp, _Tp> && convertible_to<_Tp, _Tp>;
|
||||
|
||||
// [concept.booleantestable]
|
||||
template<class _Tp>
|
||||
concept __boolean_testable_impl = convertible_to<_Tp, bool>;
|
||||
|
||||
template<class _Tp>
|
||||
concept __boolean_testable = __boolean_testable_impl<_Tp> && requires(_Tp&& __t) {
|
||||
{ !std::forward<_Tp>(__t) } -> __boolean_testable_impl;
|
||||
};
|
||||
|
||||
// [concept.equalitycomparable]
|
||||
template<class _Tp, class _Up>
|
||||
concept __weakly_equality_comparable_with =
|
||||
requires(const remove_reference_t<_Tp>& __t, const remove_reference_t<_Up>& __u) {
|
||||
{ __t == __u } -> __boolean_testable;
|
||||
{ __t != __u } -> __boolean_testable;
|
||||
{ __u == __t } -> __boolean_testable;
|
||||
{ __u != __t } -> __boolean_testable;
|
||||
};
|
||||
|
||||
template<class _Tp>
|
||||
concept equality_comparable = __weakly_equality_comparable_with<_Tp, _Tp>;
|
||||
|
||||
template<class _Tp, class _Up>
|
||||
concept equality_comparable_with =
|
||||
equality_comparable<_Tp> && equality_comparable<_Up> &&
|
||||
common_reference_with<const remove_reference_t<_Tp>&, const remove_reference_t<_Up>&> &&
|
||||
equality_comparable<
|
||||
common_reference_t<
|
||||
const remove_reference_t<_Tp>&,
|
||||
const remove_reference_t<_Up>&>> &&
|
||||
__weakly_equality_comparable_with<_Tp, _Up>;
|
||||
|
||||
// [concept.copyconstructible]
|
||||
template<class _Tp>
|
||||
concept copy_constructible =
|
||||
|
|
|
@ -0,0 +1,143 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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<class T>
|
||||
// concept equality_comparable = // see below
|
||||
|
||||
#include <concepts>
|
||||
|
||||
#include <array>
|
||||
#include <deque>
|
||||
#include <forward_list>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <optional>
|
||||
#include <set>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
#include "../types.h"
|
||||
|
||||
namespace fundamentals {
|
||||
static_assert(std::equality_comparable<int>);
|
||||
static_assert(std::equality_comparable<double>);
|
||||
static_assert(std::equality_comparable<void*>);
|
||||
static_assert(std::equality_comparable<char*>);
|
||||
static_assert(std::equality_comparable<char const*>);
|
||||
static_assert(std::equality_comparable<char volatile*>);
|
||||
static_assert(std::equality_comparable<char const volatile*>);
|
||||
static_assert(std::equality_comparable<wchar_t&>);
|
||||
static_assert(std::equality_comparable<char8_t const&>);
|
||||
static_assert(std::equality_comparable<char16_t volatile&>);
|
||||
static_assert(std::equality_comparable<char32_t const volatile&>);
|
||||
static_assert(std::equality_comparable<unsigned char&&>);
|
||||
static_assert(std::equality_comparable<unsigned short const&&>);
|
||||
static_assert(std::equality_comparable<unsigned int volatile&&>);
|
||||
static_assert(std::equality_comparable<unsigned long const volatile&&>);
|
||||
static_assert(std::equality_comparable<int[5]>);
|
||||
static_assert(std::equality_comparable<int (*)(int)>);
|
||||
static_assert(std::equality_comparable<int (&)(int)>);
|
||||
static_assert(std::equality_comparable<int (*)(int) noexcept>);
|
||||
static_assert(std::equality_comparable<int (&)(int) noexcept>);
|
||||
static_assert(std::equality_comparable<std::nullptr_t>);
|
||||
|
||||
struct S {};
|
||||
static_assert(std::equality_comparable<int S::*>);
|
||||
static_assert(std::equality_comparable<int (S::*)()>);
|
||||
static_assert(std::equality_comparable<int (S::*)() noexcept>);
|
||||
static_assert(std::equality_comparable<int (S::*)() &>);
|
||||
static_assert(std::equality_comparable<int (S::*)() & noexcept>);
|
||||
static_assert(std::equality_comparable<int (S::*)() &&>);
|
||||
static_assert(std::equality_comparable<int (S::*)() && noexcept>);
|
||||
static_assert(std::equality_comparable<int (S::*)() const>);
|
||||
static_assert(std::equality_comparable<int (S::*)() const noexcept>);
|
||||
static_assert(std::equality_comparable<int (S::*)() const&>);
|
||||
static_assert(std::equality_comparable<int (S::*)() const & noexcept>);
|
||||
static_assert(std::equality_comparable<int (S::*)() const&&>);
|
||||
static_assert(std::equality_comparable<int (S::*)() const && noexcept>);
|
||||
static_assert(std::equality_comparable<int (S::*)() volatile>);
|
||||
static_assert(std::equality_comparable<int (S::*)() volatile noexcept>);
|
||||
static_assert(std::equality_comparable<int (S::*)() volatile&>);
|
||||
static_assert(std::equality_comparable<int (S::*)() volatile & noexcept>);
|
||||
static_assert(std::equality_comparable<int (S::*)() volatile&&>);
|
||||
static_assert(std::equality_comparable<int (S::*)() volatile && noexcept>);
|
||||
static_assert(std::equality_comparable<int (S::*)() const volatile>);
|
||||
static_assert(std::equality_comparable<int (S::*)() const volatile noexcept>);
|
||||
static_assert(std::equality_comparable<int (S::*)() const volatile&>);
|
||||
static_assert(std::equality_comparable<int (S::*)() const volatile & noexcept>);
|
||||
static_assert(std::equality_comparable<int (S::*)() const volatile&&>);
|
||||
static_assert(
|
||||
std::equality_comparable<int (S::*)() const volatile && noexcept>);
|
||||
|
||||
static_assert(!std::equality_comparable<void>);
|
||||
} // namespace fundamentals
|
||||
|
||||
namespace standard_types {
|
||||
static_assert(std::equality_comparable<std::array<int, 10> >);
|
||||
static_assert(std::equality_comparable<std::deque<int> >);
|
||||
static_assert(std::equality_comparable<std::forward_list<int> >);
|
||||
static_assert(std::equality_comparable<std::list<int> >);
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_THREADS
|
||||
static_assert(!std::equality_comparable<std::lock_guard<std::mutex> >);
|
||||
static_assert(std::equality_comparable<std::map<int, void*> >);
|
||||
static_assert(!std::equality_comparable<std::mutex>);
|
||||
static_assert(
|
||||
!std::equality_comparable<std::optional<std::lock_guard<std::mutex> > >);
|
||||
static_assert(!std::equality_comparable<std::optional<std::mutex> >);
|
||||
#endif
|
||||
|
||||
static_assert(std::equality_comparable<std::optional<int> >);
|
||||
static_assert(std::equality_comparable<std::set<int> >);
|
||||
static_assert(std::equality_comparable<std::unordered_map<int, void*> >);
|
||||
static_assert(std::equality_comparable<std::unordered_set<int> >);
|
||||
static_assert(std::equality_comparable<std::vector<bool> >);
|
||||
static_assert(std::equality_comparable<std::vector<int> >);
|
||||
} // namespace standard_types
|
||||
|
||||
namespace types_fit_for_purpose {
|
||||
static_assert(std::equality_comparable<cxx20_member_eq>);
|
||||
static_assert(std::equality_comparable<cxx20_friend_eq>);
|
||||
static_assert(std::equality_comparable<member_three_way_comparable>);
|
||||
static_assert(std::equality_comparable<friend_three_way_comparable>);
|
||||
static_assert(std::equality_comparable<explicit_operators>);
|
||||
static_assert(std::equality_comparable<eq_neq_different_return_types>);
|
||||
static_assert(std::equality_comparable<one_member_one_friend>);
|
||||
static_assert(std::equality_comparable<equality_comparable_with_ec1>);
|
||||
|
||||
static_assert(!std::equality_comparable<no_eq>);
|
||||
static_assert(!std::equality_comparable<no_neq>);
|
||||
static_assert(!std::equality_comparable<wrong_return_type_eq>);
|
||||
static_assert(!std::equality_comparable<wrong_return_type_ne>);
|
||||
static_assert(!std::equality_comparable<wrong_return_type>);
|
||||
static_assert(
|
||||
!std::equality_comparable<cxx20_member_eq_operator_with_deleted_ne>);
|
||||
static_assert(
|
||||
!std::equality_comparable<cxx20_friend_eq_operator_with_deleted_ne>);
|
||||
static_assert(
|
||||
!std::equality_comparable<member_three_way_comparable_with_deleted_eq>);
|
||||
static_assert(
|
||||
!std::equality_comparable<member_three_way_comparable_with_deleted_ne>);
|
||||
static_assert(
|
||||
!std::equality_comparable<friend_three_way_comparable_with_deleted_eq>);
|
||||
static_assert(
|
||||
!std::equality_comparable<friend_three_way_comparable_with_deleted_ne>);
|
||||
|
||||
static_assert(!std::equality_comparable<returns_explicit_bool>);
|
||||
static_assert(std::equality_comparable<returns_true_type>);
|
||||
static_assert(std::equality_comparable<returns_false_type>);
|
||||
static_assert(std::equality_comparable<returns_int_ptr>);
|
||||
} // namespace types_fit_for_purpose
|
||||
|
||||
int main(int, char**) { return 0; }
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,200 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#ifndef TEST_STD_CONCEPTS_COMPARISON_EQUALITYCOMPARABLE_H
|
||||
#define TEST_STD_CONCEPTS_COMPARISON_EQUALITYCOMPARABLE_H
|
||||
|
||||
#include <compare>
|
||||
#include <concepts>
|
||||
#include <type_traits>
|
||||
|
||||
// `noexcept` specifiers deliberately imperfect since not all programmers bother to put the
|
||||
// specifiers on their overloads.
|
||||
|
||||
struct equality_comparable_with_ec1;
|
||||
struct no_neq;
|
||||
|
||||
struct cxx20_member_eq {
|
||||
bool operator==(cxx20_member_eq const&) const = default;
|
||||
};
|
||||
|
||||
struct cxx20_friend_eq {
|
||||
friend bool operator==(cxx20_friend_eq const&,
|
||||
cxx20_friend_eq const&) = default;
|
||||
};
|
||||
|
||||
struct member_three_way_comparable {
|
||||
auto operator<=>(member_three_way_comparable const&) const = default;
|
||||
};
|
||||
|
||||
struct friend_three_way_comparable {
|
||||
friend auto operator<=>(friend_three_way_comparable const&,
|
||||
friend_three_way_comparable const&) = default;
|
||||
};
|
||||
|
||||
struct explicit_operators {
|
||||
friend bool operator==(explicit_operators, explicit_operators) noexcept;
|
||||
friend bool operator!=(explicit_operators, explicit_operators) noexcept;
|
||||
|
||||
friend bool operator==(explicit_operators const&,
|
||||
equality_comparable_with_ec1 const&) noexcept;
|
||||
friend bool operator==(equality_comparable_with_ec1 const&,
|
||||
explicit_operators const&) noexcept;
|
||||
friend bool operator!=(explicit_operators const&,
|
||||
equality_comparable_with_ec1 const&) noexcept;
|
||||
friend bool operator!=(equality_comparable_with_ec1 const&,
|
||||
explicit_operators const&) noexcept;
|
||||
};
|
||||
|
||||
struct eq_neq_different_return_types {
|
||||
int operator==(eq_neq_different_return_types) const noexcept;
|
||||
friend long operator!=(eq_neq_different_return_types,
|
||||
eq_neq_different_return_types) noexcept;
|
||||
|
||||
friend int operator==(explicit_operators, eq_neq_different_return_types);
|
||||
friend int operator==(eq_neq_different_return_types, explicit_operators);
|
||||
friend long operator!=(explicit_operators, eq_neq_different_return_types);
|
||||
friend long operator!=(eq_neq_different_return_types, explicit_operators);
|
||||
|
||||
operator explicit_operators() const;
|
||||
};
|
||||
|
||||
struct boolean {
|
||||
operator bool() const noexcept;
|
||||
};
|
||||
|
||||
struct one_member_one_friend {
|
||||
friend boolean operator==(one_member_one_friend,
|
||||
one_member_one_friend) noexcept;
|
||||
boolean operator!=(one_member_one_friend) const noexcept;
|
||||
|
||||
operator explicit_operators() const noexcept;
|
||||
operator eq_neq_different_return_types() const noexcept;
|
||||
};
|
||||
|
||||
struct equality_comparable_with_ec1 {
|
||||
bool operator==(equality_comparable_with_ec1) const noexcept;
|
||||
bool operator!=(equality_comparable_with_ec1) const noexcept;
|
||||
operator explicit_operators() const noexcept;
|
||||
};
|
||||
|
||||
struct no_eq {
|
||||
friend bool operator!=(no_eq, no_eq) noexcept;
|
||||
};
|
||||
|
||||
struct no_neq {
|
||||
friend bool operator==(no_neq, no_neq) noexcept;
|
||||
friend bool operator!=(no_neq, no_neq) = delete;
|
||||
};
|
||||
|
||||
struct wrong_return_type_eq {
|
||||
void operator==(wrong_return_type_eq) const noexcept;
|
||||
bool operator!=(wrong_return_type_eq) const noexcept;
|
||||
};
|
||||
|
||||
struct wrong_return_type_ne {
|
||||
bool operator==(wrong_return_type_ne) const noexcept;
|
||||
void operator!=(wrong_return_type_ne) const noexcept;
|
||||
};
|
||||
|
||||
struct wrong_return_type {
|
||||
void operator==(wrong_return_type) const noexcept;
|
||||
void operator!=(wrong_return_type) const noexcept;
|
||||
};
|
||||
|
||||
struct cxx20_member_eq_operator_with_deleted_ne {
|
||||
bool
|
||||
operator==(cxx20_member_eq_operator_with_deleted_ne const&) const = default;
|
||||
bool
|
||||
operator!=(cxx20_member_eq_operator_with_deleted_ne const&) const = delete;
|
||||
};
|
||||
|
||||
struct cxx20_friend_eq_operator_with_deleted_ne {
|
||||
friend bool
|
||||
operator==(cxx20_friend_eq_operator_with_deleted_ne const&,
|
||||
cxx20_friend_eq_operator_with_deleted_ne const&) = default;
|
||||
friend bool
|
||||
operator!=(cxx20_friend_eq_operator_with_deleted_ne const&,
|
||||
cxx20_friend_eq_operator_with_deleted_ne const&) = delete;
|
||||
};
|
||||
|
||||
struct member_three_way_comparable_with_deleted_eq {
|
||||
auto operator<=>(member_three_way_comparable_with_deleted_eq const&) const =
|
||||
default;
|
||||
auto
|
||||
operator==(member_three_way_comparable_with_deleted_eq const&) const = delete;
|
||||
};
|
||||
|
||||
struct member_three_way_comparable_with_deleted_ne {
|
||||
auto operator<=>(member_three_way_comparable_with_deleted_ne const&) const =
|
||||
default;
|
||||
auto
|
||||
operator!=(member_three_way_comparable_with_deleted_ne const&) const = delete;
|
||||
};
|
||||
|
||||
struct friend_three_way_comparable_with_deleted_eq {
|
||||
friend auto
|
||||
operator<=>(friend_three_way_comparable_with_deleted_eq const&,
|
||||
friend_three_way_comparable_with_deleted_eq const&) = default;
|
||||
friend auto
|
||||
operator==(friend_three_way_comparable_with_deleted_eq const&,
|
||||
friend_three_way_comparable_with_deleted_eq const&) = delete;
|
||||
};
|
||||
|
||||
struct friend_three_way_comparable_with_deleted_ne {
|
||||
friend auto
|
||||
operator<=>(friend_three_way_comparable_with_deleted_ne const&,
|
||||
friend_three_way_comparable_with_deleted_ne const&) = default;
|
||||
friend auto
|
||||
operator!=(friend_three_way_comparable_with_deleted_ne const&,
|
||||
friend_three_way_comparable_with_deleted_ne const&) = delete;
|
||||
};
|
||||
|
||||
struct one_way_eq {
|
||||
bool operator==(one_way_eq const&) const = default;
|
||||
friend bool operator==(one_way_eq, explicit_operators);
|
||||
friend bool operator==(explicit_operators, one_way_eq) = delete;
|
||||
|
||||
operator explicit_operators() const;
|
||||
};
|
||||
|
||||
struct one_way_ne {
|
||||
bool operator==(one_way_ne const&) const = default;
|
||||
friend bool operator==(one_way_ne, explicit_operators);
|
||||
friend bool operator!=(one_way_ne, explicit_operators) = delete;
|
||||
|
||||
operator explicit_operators() const;
|
||||
};
|
||||
static_assert(requires(explicit_operators const x, one_way_ne const y) {
|
||||
x != y;
|
||||
});
|
||||
|
||||
struct explicit_bool {
|
||||
explicit operator bool() const noexcept;
|
||||
};
|
||||
|
||||
struct returns_explicit_bool {
|
||||
friend explicit_bool operator==(returns_explicit_bool, returns_explicit_bool);
|
||||
friend explicit_bool operator!=(returns_explicit_bool, returns_explicit_bool);
|
||||
};
|
||||
|
||||
struct returns_true_type {
|
||||
friend std::true_type operator==(returns_true_type, returns_true_type);
|
||||
friend std::true_type operator!=(returns_true_type, returns_true_type);
|
||||
};
|
||||
|
||||
struct returns_false_type {
|
||||
friend std::false_type operator==(returns_false_type, returns_false_type);
|
||||
friend std::false_type operator!=(returns_false_type, returns_false_type);
|
||||
};
|
||||
|
||||
struct returns_int_ptr {
|
||||
friend int* operator==(returns_int_ptr, returns_int_ptr);
|
||||
friend int* operator!=(returns_int_ptr, returns_int_ptr);
|
||||
};
|
||||
|
||||
#endif // TEST_STD_CONCEPTS_COMPARISON_EQUALITYCOMPARABLE_H
|
Loading…
Reference in New Issue