Skip to content

Commit 2d9efcf

Browse files
committed
[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
1 parent 4e24ca1 commit 2d9efcf

File tree

11 files changed

+247
-15
lines changed

11 files changed

+247
-15
lines changed

libcxx/docs/Status/RangesPaper.csv

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ Section,Description,Dependencies,Assignee,Complete
1717
| *no-throw-input-range*
1818
| *no-throw-forward-iterator*
1919
| *no-throw-forward-range*","| [iterator.concepts]
20-
| [range.refinements]",Konstantin Varlamov,Not started
20+
| [range.refinements]",Konstantin Varlamov,
2121
`[specialized.algorithms] <http://wg21.link/specialized.algorithms>`_,"| ranges::uninitialized_default_construct
2222
| ranges::uninitialized_default_construct_n
2323
| ranges::uninitialized_value_construct

libcxx/include/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,7 @@ set(files
228228
__memory/allocator.h
229229
__memory/auto_ptr.h
230230
__memory/compressed_pair.h
231+
__memory/concepts.h
231232
__memory/construct_at.h
232233
__memory/pointer_traits.h
233234
__memory/raw_storage_iterator.h

libcxx/include/__memory/concepts.h

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
// -*- C++ -*-
2+
//===----------------------------------------------------------------------===//
3+
//
4+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5+
// See https://llvm.org/LICENSE.txt for license information.
6+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7+
//
8+
//===----------------------------------------------------------------------===//
9+
10+
#ifndef _LIBCPP___MEMORY_CONCEPTS_H
11+
#define _LIBCPP___MEMORY_CONCEPTS_H
12+
13+
#include <__config>
14+
#include <__iterator/concepts.h>
15+
#include <__iterator/iterator_traits.h>
16+
#include <__iterator/readable_traits.h>
17+
#include <__ranges/access.h>
18+
#include <__ranges/concepts.h>
19+
#include <concepts>
20+
#include <type_traits>
21+
22+
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
23+
#pragma GCC system_header
24+
#endif
25+
26+
_LIBCPP_BEGIN_NAMESPACE_STD
27+
28+
#if !defined(_LIBCPP_HAS_NO_RANGES)
29+
namespace ranges {
30+
31+
// [special.mem.concepts]
32+
33+
// This concept ensures that uninitialized algorithms can construct an object
34+
// at the address pointed-to by the iterator, which requires an lvalue.
35+
template <class _Ip>
36+
concept __nothrow_input_iterator =
37+
input_iterator<_Ip> &&
38+
is_lvalue_reference_v<iter_reference_t<_Ip>> &&
39+
same_as<remove_cvref_t<iter_reference_t<_Ip>>, iter_value_t<_Ip>>;
40+
41+
template <class _Sp, class _Ip>
42+
concept __nothrow_sentinel_for = sentinel_for<_Sp, _Ip>;
43+
44+
template <class _Rp>
45+
concept __nothrow_input_range =
46+
range<_Rp> &&
47+
__nothrow_input_iterator<iterator_t<_Rp>> &&
48+
__nothrow_sentinel_for<sentinel_t<_Rp>, iterator_t<_Rp>>;
49+
50+
template <class _Ip>
51+
concept __nothrow_forward_iterator =
52+
__nothrow_input_iterator<_Ip> &&
53+
forward_iterator<_Ip> &&
54+
__nothrow_sentinel_for<_Ip, _Ip>;
55+
56+
template <class _Rp>
57+
concept __nothrow_forward_range =
58+
__nothrow_input_range<_Rp> &&
59+
__nothrow_forward_iterator<iterator_t<_Rp>>;
60+
61+
} // namespace ranges
62+
#endif // !defined(_LIBCPP_HAS_NO_RANGES)
63+
64+
_LIBCPP_END_NAMESPACE_STD
65+
66+
#endif // _LIBCPP___MEMORY_CONCEPTS_H

libcxx/include/memory

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -669,6 +669,7 @@ void* align(size_t alignment, size_t size, void*& ptr, size_t& space);
669669
#include <__memory/allocator_arg_t.h>
670670
#include <__memory/allocator_traits.h>
671671
#include <__memory/compressed_pair.h>
672+
#include <__memory/concepts.h>
672673
#include <__memory/construct_at.h>
673674
#include <__memory/pointer_traits.h>
674675
#include <__memory/raw_storage_iterator.h>

libcxx/include/module.modulemap

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -630,21 +630,22 @@ module std [system] {
630630
export *
631631

632632
module __memory {
633-
module addressof { private header "__memory/addressof.h" }
634-
module allocation_guard { private header "__memory/allocation_guard.h" }
635-
module allocator { private header "__memory/allocator.h" }
636-
module allocator_arg_t { private header "__memory/allocator_arg_t.h" }
637-
module allocator_traits { private header "__memory/allocator_traits.h" }
638-
module auto_ptr { private header "__memory/auto_ptr.h" }
639-
module compressed_pair { private header "__memory/compressed_pair.h" }
640-
module construct_at { private header "__memory/construct_at.h" }
641-
module pointer_traits { private header "__memory/pointer_traits.h" }
642-
module raw_storage_iterator { private header "__memory/raw_storage_iterator.h" }
643-
module shared_ptr { private header "__memory/shared_ptr.h" }
644-
module temporary_buffer { private header "__memory/temporary_buffer.h" }
633+
module addressof { private header "__memory/addressof.h" }
634+
module allocation_guard { private header "__memory/allocation_guard.h" }
635+
module allocator { private header "__memory/allocator.h" }
636+
module allocator_arg_t { private header "__memory/allocator_arg_t.h" }
637+
module allocator_traits { private header "__memory/allocator_traits.h" }
638+
module auto_ptr { private header "__memory/auto_ptr.h" }
639+
module compressed_pair { private header "__memory/compressed_pair.h" }
640+
module concepts { private header "__memory/concepts.h" }
641+
module construct_at { private header "__memory/construct_at.h" }
642+
module pointer_traits { private header "__memory/pointer_traits.h" }
643+
module raw_storage_iterator { private header "__memory/raw_storage_iterator.h" }
644+
module shared_ptr { private header "__memory/shared_ptr.h" }
645+
module temporary_buffer { private header "__memory/temporary_buffer.h" }
645646
module uninitialized_algorithms { private header "__memory/uninitialized_algorithms.h" }
646-
module unique_ptr { private header "__memory/unique_ptr.h" }
647-
module uses_allocator { private header "__memory/uses_allocator.h" }
647+
module unique_ptr { private header "__memory/unique_ptr.h" }
648+
module uses_allocator { private header "__memory/uses_allocator.h" }
648649
}
649650
}
650651
module mutex {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
// UNSUPPORTED: c++03, c++11, c++14, c++17
10+
// UNSUPPORTED: libcpp-no-concepts
11+
12+
// template<class I>
13+
// concept __nothrow_forward_iterator;
14+
15+
#include <memory>
16+
17+
#include "test_iterators.h"
18+
19+
struct ForwardProxyIterator {
20+
using value_type = int;
21+
using difference_type = int;
22+
ForwardProxyIterator& operator++();
23+
ForwardProxyIterator operator++(int);
24+
bool operator==(const ForwardProxyIterator&) const;
25+
26+
int operator*() const;
27+
};
28+
29+
static_assert(std::ranges::__nothrow_forward_iterator<forward_iterator<int*>>);
30+
static_assert(std::forward_iterator<ForwardProxyIterator>);
31+
static_assert(!std::ranges::__nothrow_forward_iterator<ForwardProxyIterator>);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
// UNSUPPORTED: c++03, c++11, c++14, c++17
10+
// UNSUPPORTED: libcpp-no-concepts
11+
12+
// template<class R>
13+
// concept __nothrow_forward_range;
14+
15+
#include <memory>
16+
17+
#include "test_iterators.h"
18+
#include "test_range.h"
19+
20+
// Has to be a template to work with `test_range`.
21+
template <typename>
22+
struct ForwardProxyIterator {
23+
using value_type = int;
24+
using difference_type = int;
25+
ForwardProxyIterator& operator++();
26+
ForwardProxyIterator operator++(int);
27+
bool operator==(const ForwardProxyIterator&) const;
28+
29+
int operator*() const;
30+
};
31+
32+
static_assert(std::ranges::__nothrow_forward_range<test_range<forward_iterator>>);
33+
static_assert(!std::ranges::__nothrow_forward_range<test_range<cpp20_input_iterator>>);
34+
static_assert(std::ranges::forward_range<test_range<ForwardProxyIterator>>);
35+
static_assert(!std::ranges::__nothrow_forward_range<test_range<ForwardProxyIterator>>);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
// UNSUPPORTED: c++03, c++11, c++14, c++17
10+
// UNSUPPORTED: libcpp-no-concepts
11+
12+
// template<class I>
13+
// concept __nothrow_input_iterator;
14+
15+
#include <memory>
16+
17+
#include "test_iterators.h"
18+
19+
struct InputProxyIterator {
20+
using value_type = int;
21+
using difference_type = int;
22+
InputProxyIterator& operator++();
23+
InputProxyIterator operator++(int);
24+
25+
int operator*() const;
26+
};
27+
28+
static_assert(std::ranges::__nothrow_input_iterator<cpp20_input_iterator<int*>>);
29+
static_assert(!std::ranges::__nothrow_input_iterator<output_iterator<int*>>);
30+
static_assert(std::input_iterator<InputProxyIterator>);
31+
static_assert(!std::ranges::__nothrow_input_iterator<InputProxyIterator>);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
// UNSUPPORTED: c++03, c++11, c++14, c++17
10+
// UNSUPPORTED: libcpp-no-concepts
11+
12+
// template<class R>
13+
// concept __nothrow_input_range;
14+
15+
#include <memory>
16+
17+
#include "test_iterators.h"
18+
#include "test_range.h"
19+
20+
// Has to be a template to work with `test_range`.
21+
template <typename>
22+
struct InputProxyIterator {
23+
using value_type = int;
24+
using difference_type = int;
25+
InputProxyIterator& operator++();
26+
InputProxyIterator operator++(int);
27+
28+
int operator*() const;
29+
};
30+
31+
static_assert(std::ranges::__nothrow_input_range<test_range<cpp20_input_iterator>>);
32+
static_assert(std::ranges::input_range<test_range<InputProxyIterator>>);
33+
static_assert(!std::ranges::__nothrow_input_range<test_range<InputProxyIterator>>);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
// UNSUPPORTED: c++03, c++11, c++14, c++17
10+
// UNSUPPORTED: libcpp-no-concepts
11+
12+
// template<class S, class I>
13+
// concept __nothrow_sentinel_for;
14+
15+
#include <memory>
16+
17+
static_assert(std::ranges::__nothrow_sentinel_for<int*, int*>);
18+
static_assert(!std::ranges::__nothrow_sentinel_for<int*, long*>);
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
// REQUIRES: modules-build
10+
11+
// WARNING: This test was generated by 'generate_private_header_tests.py'
12+
// and should not be edited manually.
13+
14+
// expected-error@*:* {{use of private header from outside its module: '__memory/concepts.h'}}
15+
#include <__memory/concepts.h>

0 commit comments

Comments
 (0)