forked from OSchip/llvm-project
[libcxx] adds `std::incrementable_traits` to <iterator>
Implements parts of: - P0896R4 The One Ranges Proposal Depends on D99041 Differential Revision: https://reviews.llvm.org/D99141
This commit is contained in:
parent
7dbb4274ef
commit
fe31f11cc8
|
@ -61,7 +61,7 @@
|
|||
"`P0608R3 <https://wg21.link/P0608R3>`__","LWG","A sane variant converting constructor","San Diego","|Complete|","9.0"
|
||||
"`P0655R1 <https://wg21.link/P0655R1>`__","LWG","visit<R>: Explicit Return Type for visit","San Diego","|Complete|","12.0"
|
||||
"`P0771R1 <https://wg21.link/P0771R1>`__","LWG","std::function move constructor should be noexcept","San Diego","|Complete|","6.0"
|
||||
"`P0896R4 <https://wg21.link/P0896R4>`__","LWG","The One Ranges Proposal","San Diego","* *",""
|
||||
"`P0896R4 <https://wg21.link/P0896R4>`__","LWG","The One Ranges Proposal","San Diego","|In Progress|",""
|
||||
"`P0899R1 <https://wg21.link/P0899R1>`__","LWG","P0899R1 - LWG 3016 is not a defect","San Diego","|Nothing To Do|",""
|
||||
"`P0919R3 <https://wg21.link/P0919R3>`__","LWG","Heterogeneous lookup for unordered containers","San Diego","|Complete|","12.0"
|
||||
"`P0972R0 <https://wg21.link/P0972R0>`__","LWG","<chrono> ``zero()``\ , ``min()``\ , and ``max()``\ should be noexcept","San Diego","|Complete|","8.0"
|
||||
|
|
|
|
@ -848,6 +848,10 @@ typedef unsigned int char32_t;
|
|||
#define _LIBCPP_HAS_NO_CONCEPTS
|
||||
#endif
|
||||
|
||||
#if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_HAS_NO_CONCEPTS)
|
||||
#define _LIBCPP_HAS_NO_RANGES
|
||||
#endif
|
||||
|
||||
#ifdef _LIBCPP_CXX03_LANG
|
||||
# define _LIBCPP_DEFAULT {}
|
||||
#else
|
||||
|
|
|
@ -13,8 +13,11 @@
|
|||
/*
|
||||
iterator synopsis
|
||||
|
||||
#include <concepts>
|
||||
|
||||
namespace std
|
||||
{
|
||||
template<class> struct incrementable_traits; // since C++20
|
||||
|
||||
template<class Iterator>
|
||||
struct iterator_traits
|
||||
|
@ -425,6 +428,7 @@ template <class E> constexpr const E* data(initializer_list<E> il) noexcept;
|
|||
#include <__memory/base.h>
|
||||
#include <__memory/pointer_traits.h>
|
||||
#include <version>
|
||||
#include <concepts>
|
||||
|
||||
#include <__debug>
|
||||
|
||||
|
@ -433,6 +437,43 @@ template <class E> constexpr const E* data(initializer_list<E> il) noexcept;
|
|||
#endif
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_RANGES)
|
||||
// [incrementable.traits]
|
||||
template<class> struct incrementable_traits {};
|
||||
|
||||
template<class _Tp>
|
||||
requires is_object_v<_Tp>
|
||||
struct incrementable_traits<_Tp*> {
|
||||
using difference_type = ptrdiff_t;
|
||||
};
|
||||
|
||||
template<class _Ip>
|
||||
struct incrementable_traits<const _Ip> : incrementable_traits<_Ip> {};
|
||||
|
||||
template<class _Tp>
|
||||
concept __has_member_difference_type = requires { typename _Tp::difference_type; };
|
||||
|
||||
template<__has_member_difference_type _Tp>
|
||||
struct incrementable_traits<_Tp> {
|
||||
using difference_type = typename _Tp::difference_type;
|
||||
};
|
||||
|
||||
template<class _Tp>
|
||||
concept __has_integral_minus =
|
||||
!__has_member_difference_type<_Tp> &&
|
||||
requires(const _Tp& __x, const _Tp& __y) {
|
||||
{ __x - __y } -> integral;
|
||||
};
|
||||
|
||||
template<__has_integral_minus _Tp>
|
||||
struct incrementable_traits<_Tp> {
|
||||
using difference_type = make_signed_t<decltype(declval<_Tp>() - declval<_Tp>())>;
|
||||
};
|
||||
|
||||
// TODO(cjdb): add iter_difference_t once iterator_traits is cleaned up.
|
||||
#endif // !defined(_LIBCPP_HAS_NO_RANGES)
|
||||
|
||||
template <class _Iter>
|
||||
struct _LIBCPP_TEMPLATE_VIS iterator_traits;
|
||||
|
||||
|
|
|
@ -0,0 +1,260 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
// UNSUPPORTED: gcc-10
|
||||
|
||||
// template<class T>
|
||||
// struct incrementable_traits;
|
||||
|
||||
#include <iterator>
|
||||
|
||||
#include <concepts>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
// clang-format off
|
||||
template <class T>
|
||||
concept check_has_difference_type = requires {
|
||||
typename std::incrementable_traits<T>::difference_type;
|
||||
};
|
||||
|
||||
template <class T, class Expected>
|
||||
concept check_difference_type_matches =
|
||||
check_has_difference_type<T> &&
|
||||
std::same_as<typename std::incrementable_traits<T>::difference_type, Expected>;
|
||||
// clang-format on
|
||||
|
||||
template <class T, class Expected>
|
||||
[[nodiscard]] constexpr bool check_incrementable_traits() noexcept {
|
||||
constexpr bool result = check_difference_type_matches<T, Expected>;
|
||||
static_assert(check_difference_type_matches<T const, Expected> == result);
|
||||
return result;
|
||||
}
|
||||
|
||||
static_assert(check_incrementable_traits<float*, std::ptrdiff_t>());
|
||||
static_assert(check_incrementable_traits<float const*, std::ptrdiff_t>());
|
||||
static_assert(check_incrementable_traits<float volatile*, std::ptrdiff_t>());
|
||||
static_assert(
|
||||
check_incrementable_traits<float const volatile*, std::ptrdiff_t>());
|
||||
static_assert(check_incrementable_traits<float**, std::ptrdiff_t>());
|
||||
|
||||
static_assert(check_incrementable_traits<int[], std::ptrdiff_t>());
|
||||
static_assert(check_incrementable_traits<int[10], std::ptrdiff_t>());
|
||||
|
||||
static_assert(check_incrementable_traits<char, int>());
|
||||
static_assert(check_incrementable_traits<signed char, int>());
|
||||
static_assert(check_incrementable_traits<unsigned char, int>());
|
||||
static_assert(check_incrementable_traits<short, int>());
|
||||
static_assert(check_incrementable_traits<unsigned short, int>());
|
||||
static_assert(check_incrementable_traits<int, int>());
|
||||
static_assert(check_incrementable_traits<unsigned int, int>());
|
||||
static_assert(check_incrementable_traits<long, long>());
|
||||
static_assert(check_incrementable_traits<unsigned long, long>());
|
||||
static_assert(check_incrementable_traits<long long, long long>());
|
||||
static_assert(check_incrementable_traits<unsigned long long, long long>());
|
||||
|
||||
static_assert(check_incrementable_traits<int&, int>());
|
||||
static_assert(check_incrementable_traits<int const&, int>());
|
||||
static_assert(check_incrementable_traits<int volatile&, int>());
|
||||
static_assert(check_incrementable_traits<int const volatile&, int>());
|
||||
static_assert(check_incrementable_traits<int&&, int>());
|
||||
static_assert(check_incrementable_traits<int const&&, int>());
|
||||
static_assert(check_incrementable_traits<int volatile&&, int>());
|
||||
static_assert(check_incrementable_traits<int const volatile&&, int>());
|
||||
|
||||
static_assert(check_incrementable_traits<int volatile, int>());
|
||||
static_assert(check_incrementable_traits<int* volatile, std::ptrdiff_t>());
|
||||
|
||||
struct integral_difference_type {
|
||||
using difference_type = int;
|
||||
};
|
||||
static_assert(check_incrementable_traits<integral_difference_type, int>());
|
||||
|
||||
struct non_integral_difference_type {
|
||||
using difference_type = void;
|
||||
};
|
||||
static_assert(check_incrementable_traits<non_integral_difference_type, void>());
|
||||
|
||||
struct int_subtraction {
|
||||
friend int operator-(int_subtraction, int_subtraction) noexcept;
|
||||
};
|
||||
static_assert(check_incrementable_traits<int_subtraction, int>());
|
||||
static_assert(!check_incrementable_traits<int_subtraction volatile&, int>());
|
||||
static_assert(
|
||||
!check_incrementable_traits<int_subtraction const volatile&, int>());
|
||||
|
||||
struct char_subtraction {
|
||||
friend char operator-(char_subtraction, char_subtraction) noexcept;
|
||||
};
|
||||
static_assert(check_incrementable_traits<char_subtraction, signed char>());
|
||||
|
||||
struct unsigned_int_subtraction_with_cv {
|
||||
friend unsigned int
|
||||
operator-(unsigned_int_subtraction_with_cv const&,
|
||||
unsigned_int_subtraction_with_cv const&) noexcept;
|
||||
friend unsigned int
|
||||
operator-(unsigned_int_subtraction_with_cv const volatile&,
|
||||
unsigned_int_subtraction_with_cv const volatile&) noexcept;
|
||||
};
|
||||
static_assert(
|
||||
check_incrementable_traits<unsigned_int_subtraction_with_cv, int>());
|
||||
static_assert(check_incrementable_traits<
|
||||
unsigned_int_subtraction_with_cv volatile&, int>());
|
||||
static_assert(check_incrementable_traits<
|
||||
unsigned_int_subtraction_with_cv const volatile&, int>());
|
||||
|
||||
struct specialised_incrementable_traits {};
|
||||
namespace std {
|
||||
template <>
|
||||
struct incrementable_traits<specialised_incrementable_traits> {
|
||||
using difference_type = int;
|
||||
};
|
||||
} // namespace std
|
||||
static_assert(
|
||||
check_incrementable_traits<specialised_incrementable_traits, int>());
|
||||
|
||||
static_assert(!check_has_difference_type<void>);
|
||||
static_assert(!check_has_difference_type<float>);
|
||||
static_assert(!check_has_difference_type<double>);
|
||||
static_assert(!check_has_difference_type<long double>);
|
||||
static_assert(!check_has_difference_type<float&>);
|
||||
static_assert(!check_has_difference_type<float const&>);
|
||||
|
||||
static_assert(!check_has_difference_type<void*>);
|
||||
static_assert(!check_has_difference_type<std::nullptr_t>);
|
||||
static_assert(!check_has_difference_type<int()>);
|
||||
static_assert(!check_has_difference_type<int() noexcept>);
|
||||
static_assert(!check_has_difference_type<int (*)()>);
|
||||
static_assert(!check_has_difference_type<int (*)() noexcept>);
|
||||
static_assert(!check_has_difference_type<int (&)()>);
|
||||
static_assert(!check_has_difference_type<int (&)() noexcept>);
|
||||
|
||||
#define TEST_POINTER_TO_MEMBER_FUNCTION(type, cv_qualifier) \
|
||||
static_assert(!check_has_difference_type<int (type::*)() cv_qualifier>); \
|
||||
static_assert( \
|
||||
!check_has_difference_type<int (type::*)() cv_qualifier noexcept>); \
|
||||
static_assert(!check_has_difference_type<int (type::*)() cv_qualifier&>); \
|
||||
static_assert( \
|
||||
!check_has_difference_type<int (type::*)() cv_qualifier & noexcept>); \
|
||||
static_assert(!check_has_difference_type<int (type::*)() cv_qualifier&&>); \
|
||||
static_assert(!check_has_difference_type < int (type::*)() \
|
||||
cv_qualifier&& noexcept >); \
|
||||
/**/
|
||||
|
||||
struct empty {};
|
||||
|
||||
#define NO_QUALIFIER
|
||||
TEST_POINTER_TO_MEMBER_FUNCTION(empty, NO_QUALIFIER);
|
||||
TEST_POINTER_TO_MEMBER_FUNCTION(empty, const);
|
||||
TEST_POINTER_TO_MEMBER_FUNCTION(empty, volatile);
|
||||
TEST_POINTER_TO_MEMBER_FUNCTION(empty, const volatile);
|
||||
|
||||
struct void_subtraction {
|
||||
friend void operator-(void_subtraction, void_subtraction) noexcept;
|
||||
};
|
||||
static_assert(!check_has_difference_type<void_subtraction>);
|
||||
|
||||
#define TEST_NOT_DIFFERENCE_TYPE(qual1, qual2) \
|
||||
struct TEST_CONCAT(test_subtraction_, __LINE__) { \
|
||||
friend int operator-(TEST_CONCAT(test_subtraction_, __LINE__) qual1, \
|
||||
TEST_CONCAT(test_subtraction_, __LINE__) qual2); \
|
||||
}; \
|
||||
static_assert(!check_has_difference_type<TEST_CONCAT(test_subtraction_, \
|
||||
__LINE__)>) /**/
|
||||
|
||||
TEST_NOT_DIFFERENCE_TYPE(&, &);
|
||||
TEST_NOT_DIFFERENCE_TYPE(&, const&);
|
||||
TEST_NOT_DIFFERENCE_TYPE(&, volatile&);
|
||||
TEST_NOT_DIFFERENCE_TYPE(&, const volatile&);
|
||||
TEST_NOT_DIFFERENCE_TYPE(&, &&);
|
||||
TEST_NOT_DIFFERENCE_TYPE(&, const&&);
|
||||
TEST_NOT_DIFFERENCE_TYPE(&, volatile&&);
|
||||
TEST_NOT_DIFFERENCE_TYPE(&, const volatile&&);
|
||||
|
||||
TEST_NOT_DIFFERENCE_TYPE(const&, &);
|
||||
// TEST_NOT_DIFFERENCE_TYPE(const&, const&); // == true
|
||||
TEST_NOT_DIFFERENCE_TYPE(const&, volatile&);
|
||||
// TEST_NOT_DIFFERENCE_TYPE(const&, const volatile&); // invalid
|
||||
TEST_NOT_DIFFERENCE_TYPE(const&, &&);
|
||||
TEST_NOT_DIFFERENCE_TYPE(const&, const&&);
|
||||
TEST_NOT_DIFFERENCE_TYPE(const&, volatile&&);
|
||||
TEST_NOT_DIFFERENCE_TYPE(const&, const volatile&&);
|
||||
|
||||
TEST_NOT_DIFFERENCE_TYPE(volatile&, &);
|
||||
TEST_NOT_DIFFERENCE_TYPE(volatile&, const&);
|
||||
TEST_NOT_DIFFERENCE_TYPE(volatile&, volatile&);
|
||||
TEST_NOT_DIFFERENCE_TYPE(volatile&, const volatile&);
|
||||
TEST_NOT_DIFFERENCE_TYPE(volatile&, &&);
|
||||
TEST_NOT_DIFFERENCE_TYPE(volatile&, const&&);
|
||||
TEST_NOT_DIFFERENCE_TYPE(volatile&, volatile&&);
|
||||
TEST_NOT_DIFFERENCE_TYPE(volatile&, const volatile&&);
|
||||
|
||||
TEST_NOT_DIFFERENCE_TYPE(const volatile&, &);
|
||||
// TEST_NOT_DIFFERENCE_TYPE(const volatile&, const&); // invalid
|
||||
TEST_NOT_DIFFERENCE_TYPE(const volatile&, volatile&);
|
||||
// TEST_NOT_DIFFERENCE_TYPE(const volatile&, const volatile&); // invalid
|
||||
TEST_NOT_DIFFERENCE_TYPE(const volatile&, &&);
|
||||
TEST_NOT_DIFFERENCE_TYPE(const volatile&, const&&);
|
||||
TEST_NOT_DIFFERENCE_TYPE(const volatile&, volatile&&);
|
||||
TEST_NOT_DIFFERENCE_TYPE(const volatile&, const volatile&&);
|
||||
|
||||
TEST_NOT_DIFFERENCE_TYPE(&&, &);
|
||||
TEST_NOT_DIFFERENCE_TYPE(&&, const&);
|
||||
TEST_NOT_DIFFERENCE_TYPE(&&, volatile&);
|
||||
TEST_NOT_DIFFERENCE_TYPE(&&, const volatile&);
|
||||
TEST_NOT_DIFFERENCE_TYPE(&&, &&);
|
||||
TEST_NOT_DIFFERENCE_TYPE(&&, const&&);
|
||||
TEST_NOT_DIFFERENCE_TYPE(&&, volatile&&);
|
||||
TEST_NOT_DIFFERENCE_TYPE(&&, const volatile&&);
|
||||
|
||||
TEST_NOT_DIFFERENCE_TYPE(const&&, &);
|
||||
TEST_NOT_DIFFERENCE_TYPE(const&&, const&);
|
||||
TEST_NOT_DIFFERENCE_TYPE(const&&, volatile&);
|
||||
TEST_NOT_DIFFERENCE_TYPE(const&&, const volatile&);
|
||||
TEST_NOT_DIFFERENCE_TYPE(const&&, &&);
|
||||
TEST_NOT_DIFFERENCE_TYPE(const&&, const&&);
|
||||
TEST_NOT_DIFFERENCE_TYPE(const&&, volatile&&);
|
||||
TEST_NOT_DIFFERENCE_TYPE(const&&, const volatile&&);
|
||||
|
||||
TEST_NOT_DIFFERENCE_TYPE(volatile&&, &);
|
||||
TEST_NOT_DIFFERENCE_TYPE(volatile&&, const&);
|
||||
TEST_NOT_DIFFERENCE_TYPE(volatile&&, volatile&);
|
||||
TEST_NOT_DIFFERENCE_TYPE(volatile&&, const volatile&);
|
||||
TEST_NOT_DIFFERENCE_TYPE(volatile&&, &&);
|
||||
TEST_NOT_DIFFERENCE_TYPE(volatile&&, const&&);
|
||||
TEST_NOT_DIFFERENCE_TYPE(volatile&&, volatile&&);
|
||||
TEST_NOT_DIFFERENCE_TYPE(volatile&&, const volatile&&);
|
||||
|
||||
TEST_NOT_DIFFERENCE_TYPE(const volatile&&, &);
|
||||
TEST_NOT_DIFFERENCE_TYPE(const volatile&&, const&);
|
||||
TEST_NOT_DIFFERENCE_TYPE(const volatile&&, volatile&);
|
||||
TEST_NOT_DIFFERENCE_TYPE(const volatile&&, const volatile&);
|
||||
TEST_NOT_DIFFERENCE_TYPE(const volatile&&, &&);
|
||||
TEST_NOT_DIFFERENCE_TYPE(const volatile&&, const&&);
|
||||
TEST_NOT_DIFFERENCE_TYPE(const volatile&&, volatile&&);
|
||||
TEST_NOT_DIFFERENCE_TYPE(const volatile&&, const volatile&&);
|
||||
|
||||
TEST_NOT_DIFFERENCE_TYPE(&, NO_QUALIFIER);
|
||||
// TEST_NOT_DIFFERENCE_TYPE(const&, NO_QUALIFIER); // == true
|
||||
TEST_NOT_DIFFERENCE_TYPE(volatile&, NO_QUALIFIER);
|
||||
// TEST_NOT_DIFFERENCE_TYPE(const volatile&, NO_QUALIFIER); // invalid
|
||||
TEST_NOT_DIFFERENCE_TYPE(&&, NO_QUALIFIER);
|
||||
TEST_NOT_DIFFERENCE_TYPE(const&&, NO_QUALIFIER);
|
||||
TEST_NOT_DIFFERENCE_TYPE(volatile&&, NO_QUALIFIER);
|
||||
TEST_NOT_DIFFERENCE_TYPE(const volatile&&, NO_QUALIFIER);
|
||||
|
||||
TEST_NOT_DIFFERENCE_TYPE(NO_QUALIFIER, &);
|
||||
// TEST_NOT_DIFFERENCE_TYPE(NO_QUALIFIER, const&); // == true
|
||||
TEST_NOT_DIFFERENCE_TYPE(NO_QUALIFIER, volatile&);
|
||||
// TEST_NOT_DIFFERENCE_TYPE(NO_QUALIFIER, const volatile&); // invalid
|
||||
TEST_NOT_DIFFERENCE_TYPE(NO_QUALIFIER, &&);
|
||||
TEST_NOT_DIFFERENCE_TYPE(NO_QUALIFIER, const&&);
|
||||
TEST_NOT_DIFFERENCE_TYPE(NO_QUALIFIER, volatile&&);
|
||||
TEST_NOT_DIFFERENCE_TYPE(NO_QUALIFIER, const volatile&&);
|
Loading…
Reference in New Issue