[libc++][ranges] Implement [special.mem.concepts].

Implement the exposition-only concepts specified in
`[special.mem.concepts]`. These are all thin wrappers over other
concepts.

Reviewed By: #libc, Quuxplusone, ldionne

Differential Revision: https://reviews.llvm.org/D114761
This commit is contained in:
Konstantin Varlamov 2021-12-02 17:57:55 -08:00
parent 4e24ca1cdc
commit 2d9efcfeec
11 changed files with 247 additions and 15 deletions

View file

@ -17,7 +17,7 @@ Section,Description,Dependencies,Assignee,Complete
| *no-throw-input-range*
| *no-throw-forward-iterator*
| *no-throw-forward-range*","| [iterator.concepts]
| [range.refinements]",Konstantin Varlamov,Not started
| [range.refinements]",Konstantin Varlamov,
`[specialized.algorithms] <http://wg21.link/specialized.algorithms>`_,"| ranges::uninitialized_default_construct
| ranges::uninitialized_default_construct_n
| ranges::uninitialized_value_construct

1 Section Description Dependencies Assignee Complete
17 [common.alg.req]: pt. 2 indirectly_swappable | [iterator.concepts] | [iterator.cust.swap] Zoe Carver
18 [common.alg.req]: pt. 3 indirectly_comparable [projected] Louis Dionne Not started
19 [common.alg.req]: pt. 4 | permutable | mergeable | sortable [iterator.concepts] Unassigned Not started
20 [std.iterator.tags] [iterator.traits] Unassigned Not started
21 `[range.iter.ops] <http://wg21.link/range.iter.ops>`_ | `ranges::advance <https://llvm.org/D101922>`_ | `ranges::distance <https://llvm.org/D102789>`_ | `ranges::next <https://llvm.org/D102563>`_ | `ranges::prev <https://llvm.org/D102564>`_ [iterator.concepts] Christopher Di Bella In progress
22 [predef.iterators] Updates to predefined iterators. | [iterator.concepts] | [iterator.cust.swap] | [iterator.cust.move] Unassigned Not started
23 [move.sentinel] [predef.iterators] Unassigned Not started

View file

@ -228,6 +228,7 @@ set(files
__memory/allocator.h
__memory/auto_ptr.h
__memory/compressed_pair.h
__memory/concepts.h
__memory/construct_at.h
__memory/pointer_traits.h
__memory/raw_storage_iterator.h

View file

@ -0,0 +1,66 @@
// -*- 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
//
//===----------------------------------------------------------------------===//
#ifndef _LIBCPP___MEMORY_CONCEPTS_H
#define _LIBCPP___MEMORY_CONCEPTS_H
#include <__config>
#include <__iterator/concepts.h>
#include <__iterator/iterator_traits.h>
#include <__iterator/readable_traits.h>
#include <__ranges/access.h>
#include <__ranges/concepts.h>
#include <concepts>
#include <type_traits>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
#pragma GCC system_header
#endif
_LIBCPP_BEGIN_NAMESPACE_STD
#if !defined(_LIBCPP_HAS_NO_RANGES)
namespace ranges {
// [special.mem.concepts]
// This concept ensures that uninitialized algorithms can construct an object
// at the address pointed-to by the iterator, which requires an lvalue.
template <class _Ip>
concept __nothrow_input_iterator =
input_iterator<_Ip> &&
is_lvalue_reference_v<iter_reference_t<_Ip>> &&
same_as<remove_cvref_t<iter_reference_t<_Ip>>, iter_value_t<_Ip>>;
template <class _Sp, class _Ip>
concept __nothrow_sentinel_for = sentinel_for<_Sp, _Ip>;
template <class _Rp>
concept __nothrow_input_range =
range<_Rp> &&
__nothrow_input_iterator<iterator_t<_Rp>> &&
__nothrow_sentinel_for<sentinel_t<_Rp>, iterator_t<_Rp>>;
template <class _Ip>
concept __nothrow_forward_iterator =
__nothrow_input_iterator<_Ip> &&
forward_iterator<_Ip> &&
__nothrow_sentinel_for<_Ip, _Ip>;
template <class _Rp>
concept __nothrow_forward_range =
__nothrow_input_range<_Rp> &&
__nothrow_forward_iterator<iterator_t<_Rp>>;
} // namespace ranges
#endif // !defined(_LIBCPP_HAS_NO_RANGES)
_LIBCPP_END_NAMESPACE_STD
#endif // _LIBCPP___MEMORY_CONCEPTS_H

View file

@ -669,6 +669,7 @@ void* align(size_t alignment, size_t size, void*& ptr, size_t& space);
#include <__memory/allocator_arg_t.h>
#include <__memory/allocator_traits.h>
#include <__memory/compressed_pair.h>
#include <__memory/concepts.h>
#include <__memory/construct_at.h>
#include <__memory/pointer_traits.h>
#include <__memory/raw_storage_iterator.h>

View file

@ -630,21 +630,22 @@ module std [system] {
export *
module __memory {
module addressof { private header "__memory/addressof.h" }
module allocation_guard { private header "__memory/allocation_guard.h" }
module allocator { private header "__memory/allocator.h" }
module allocator_arg_t { private header "__memory/allocator_arg_t.h" }
module allocator_traits { private header "__memory/allocator_traits.h" }
module auto_ptr { private header "__memory/auto_ptr.h" }
module compressed_pair { private header "__memory/compressed_pair.h" }
module construct_at { private header "__memory/construct_at.h" }
module pointer_traits { private header "__memory/pointer_traits.h" }
module raw_storage_iterator { private header "__memory/raw_storage_iterator.h" }
module shared_ptr { private header "__memory/shared_ptr.h" }
module temporary_buffer { private header "__memory/temporary_buffer.h" }
module addressof { private header "__memory/addressof.h" }
module allocation_guard { private header "__memory/allocation_guard.h" }
module allocator { private header "__memory/allocator.h" }
module allocator_arg_t { private header "__memory/allocator_arg_t.h" }
module allocator_traits { private header "__memory/allocator_traits.h" }
module auto_ptr { private header "__memory/auto_ptr.h" }
module compressed_pair { private header "__memory/compressed_pair.h" }
module concepts { private header "__memory/concepts.h" }
module construct_at { private header "__memory/construct_at.h" }
module pointer_traits { private header "__memory/pointer_traits.h" }
module raw_storage_iterator { private header "__memory/raw_storage_iterator.h" }
module shared_ptr { private header "__memory/shared_ptr.h" }
module temporary_buffer { private header "__memory/temporary_buffer.h" }
module uninitialized_algorithms { private header "__memory/uninitialized_algorithms.h" }
module unique_ptr { private header "__memory/unique_ptr.h" }
module uses_allocator { private header "__memory/uses_allocator.h" }
module unique_ptr { private header "__memory/unique_ptr.h" }
module uses_allocator { private header "__memory/uses_allocator.h" }
}
}
module mutex {

View file

@ -0,0 +1,31 @@
//===----------------------------------------------------------------------===//
//
// 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 I>
// concept __nothrow_forward_iterator;
#include <memory>
#include "test_iterators.h"
struct ForwardProxyIterator {
using value_type = int;
using difference_type = int;
ForwardProxyIterator& operator++();
ForwardProxyIterator operator++(int);
bool operator==(const ForwardProxyIterator&) const;
int operator*() const;
};
static_assert(std::ranges::__nothrow_forward_iterator<forward_iterator<int*>>);
static_assert(std::forward_iterator<ForwardProxyIterator>);
static_assert(!std::ranges::__nothrow_forward_iterator<ForwardProxyIterator>);

View file

@ -0,0 +1,35 @@
//===----------------------------------------------------------------------===//
//
// 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 R>
// concept __nothrow_forward_range;
#include <memory>
#include "test_iterators.h"
#include "test_range.h"
// Has to be a template to work with `test_range`.
template <typename>
struct ForwardProxyIterator {
using value_type = int;
using difference_type = int;
ForwardProxyIterator& operator++();
ForwardProxyIterator operator++(int);
bool operator==(const ForwardProxyIterator&) const;
int operator*() const;
};
static_assert(std::ranges::__nothrow_forward_range<test_range<forward_iterator>>);
static_assert(!std::ranges::__nothrow_forward_range<test_range<cpp20_input_iterator>>);
static_assert(std::ranges::forward_range<test_range<ForwardProxyIterator>>);
static_assert(!std::ranges::__nothrow_forward_range<test_range<ForwardProxyIterator>>);

View file

@ -0,0 +1,31 @@
//===----------------------------------------------------------------------===//
//
// 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 I>
// concept __nothrow_input_iterator;
#include <memory>
#include "test_iterators.h"
struct InputProxyIterator {
using value_type = int;
using difference_type = int;
InputProxyIterator& operator++();
InputProxyIterator operator++(int);
int operator*() const;
};
static_assert(std::ranges::__nothrow_input_iterator<cpp20_input_iterator<int*>>);
static_assert(!std::ranges::__nothrow_input_iterator<output_iterator<int*>>);
static_assert(std::input_iterator<InputProxyIterator>);
static_assert(!std::ranges::__nothrow_input_iterator<InputProxyIterator>);

View file

@ -0,0 +1,33 @@
//===----------------------------------------------------------------------===//
//
// 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 R>
// concept __nothrow_input_range;
#include <memory>
#include "test_iterators.h"
#include "test_range.h"
// Has to be a template to work with `test_range`.
template <typename>
struct InputProxyIterator {
using value_type = int;
using difference_type = int;
InputProxyIterator& operator++();
InputProxyIterator operator++(int);
int operator*() const;
};
static_assert(std::ranges::__nothrow_input_range<test_range<cpp20_input_iterator>>);
static_assert(std::ranges::input_range<test_range<InputProxyIterator>>);
static_assert(!std::ranges::__nothrow_input_range<test_range<InputProxyIterator>>);

View file

@ -0,0 +1,18 @@
//===----------------------------------------------------------------------===//
//
// 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 S, class I>
// concept __nothrow_sentinel_for;
#include <memory>
static_assert(std::ranges::__nothrow_sentinel_for<int*, int*>);
static_assert(!std::ranges::__nothrow_sentinel_for<int*, long*>);

View file

@ -0,0 +1,15 @@
//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
// REQUIRES: modules-build
// WARNING: This test was generated by 'generate_private_header_tests.py'
// and should not be edited manually.
// expected-error@*:* {{use of private header from outside its module: '__memory/concepts.h'}}
#include <__memory/concepts.h>