Skip to content

Commit 18655cb

Browse files
jensmaurertkoeppe
authored andcommitted
P0401R6 Providing size feedback in the Allocator interface
1 parent a287dbd commit 18655cb

File tree

3 files changed

+114
-9
lines changed

3 files changed

+114
-9
lines changed

source/lib-intro.tex

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1916,9 +1916,7 @@
19161916
is small. That is, there is no need for a container to maintain its own
19171917
free list.
19181918
\end{footnote}
1919-
\begin{tailnote}
1920-
If \tcode{n == 0}, the return value is unspecified.
1921-
\end{tailnote}
1919+
See Note C, below.
19221920
& \\ \rowsep
19231921

19241922
\tcode{a.allocate(n, y)} &
@@ -1927,12 +1925,36 @@
19271925
it is intended as an aid to locality. &
19281926
\tcode{a.allocate(n)} \\ \rowsep
19291927

1928+
\tcode{a.allocate_at_least(n)} &
1929+
\tcode{allocation_result<X::pointer>} &
1930+
\returns
1931+
\tcode{allocation_result<X::pointer>\{ptr, count\}}
1932+
where \tcode{ptr} is memory allocated for an array of \tcode{count} \tcode{T}
1933+
and such an object is created but array elements are not constructed,
1934+
such that $\tcode{count} \geq \tcode{n}$.
1935+
\tcode{allocate_at_least} may throw an appropriate exception.
1936+
See Note C, below. &
1937+
See Note D, below. \\ \rowsep
1938+
19301939
\tcode{a.deallocate(p,n)} &
19311940
(not used) &
1932-
\expects \tcode{p} is a value returned by an earlier call
1933-
to \tcode{allocate} that has not been invalidated by
1934-
an intervening call to \tcode{deallocate}. \tcode{n}
1935-
matches the value passed to \tcode{allocate} to obtain this memory.\br
1941+
\expects
1942+
\begin{itemize}
1943+
\item
1944+
If \tcode{p} is memory
1945+
that was obtained by a call to \tcode{a.allocate_at_least},
1946+
let \tcode{ret} be the value returned and
1947+
\tcode{req} be the value passed as the first argument of that call.
1948+
\tcode{p} is equal to \tcode{ret.ptr} and
1949+
\tcode{n} is a value such that
1950+
$\tcode{req} \leq \tcode{n} \leq \tcode{ret.count}$.
1951+
\item
1952+
Otherwise, \tcode{p} is a pointer value obtained from \tcode{allocate}.
1953+
\tcode{n} equals the value passed as the first argument
1954+
to the invocation of \tcode{allocate} which returned \tcode{p}.
1955+
\end{itemize}
1956+
\tcode{p} has not been invalidated by
1957+
an intervening call to \tcode{deallocate}.\br
19361958
\throws Nothing. & \\ \rowsep
19371959

19381960
\tcode{a.max_size()} &
@@ -2060,6 +2082,17 @@
20602082
lvalues of type \tcode{X} shall be swappable\iref{swappable.requirements}
20612083
and the \tcode{swap} operation shall not throw exceptions.
20622084

2085+
\pnum
2086+
Note C:
2087+
If \tcode{n == 0}, the return value is unspecified.
2088+
2089+
\pnum
2090+
Note D:
2091+
An allocator need not support \tcode{allocate_at_least},
2092+
but no default is provided in \tcode{allocator_traits}.
2093+
If an allocator has an \tcode{allocate_at_least} member,
2094+
it shall satisify the requirements.
2095+
20632096
\pnum
20642097
An allocator type \tcode{X} shall meet the
20652098
\oldconcept{CopyConstructible} requirements (\tref{cpp17.copyconstructible}).

source/support.tex

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -553,6 +553,7 @@
553553

554554
\begin{codeblock}
555555
#define @\defnlibxname{cpp_lib_addressof_constexpr}@ 201603L // also in \libheader{memory}
556+
#define @\defnlibxname{cpp_lib_allocate_at_least}@ 202106L // also in \libheader{memory}
556557
#define @\defnlibxname{cpp_lib_allocator_traits_is_always_equal}@ 201411L
557558
// also in \libheader{memory}, \libheader{scoped_allocator}, \libheader{string}, \libheader{deque}, \libheader{forward_list}, \libheader{list}, \libheader{vector},
558559
// \libheader{map}, \libheader{set}, \libheader{unordered_map}, \libheader{unordered_set}

source/utilities.tex

Lines changed: 73 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6897,6 +6897,16 @@
68976897
// \ref{allocator.traits}, allocator traits
68986898
template<class Alloc> struct allocator_traits;
68996899

6900+
template<class Pointer>
6901+
struct allocation_result {
6902+
Pointer ptr;
6903+
size_t count;
6904+
};
6905+
6906+
template<class Allocator>
6907+
[[nodiscard] constexpr allocation_result<typename allocator_traits<Allocator>::pointer>
6908+
allocate_at_least(Allocator& a, size_t n);
6909+
69006910
// \ref{default.allocator}, the default allocator
69016911
template<class T> class allocator;
69026912
template<class T, class U>
@@ -8136,6 +8146,26 @@
81368146
well-formed; otherwise, \tcode{rhs}.
81378147
\end{itemdescr}
81388148

8149+
\rSec3[allocator.traits.other]{Other}
8150+
8151+
\pnum
8152+
The class template \tcode{allocation_result} has
8153+
the template parameters, data members, and special members specified above.
8154+
It has no base classes or members other than those specified.
8155+
8156+
\begin{itemdecl}
8157+
template<class Allocator>
8158+
[[nodiscard]] constexpr allocation_result<typename allocator_traits<Allocator>::pointer>
8159+
allocate_at_least(Allocator& a, size_t n);
8160+
\end{itemdecl}
8161+
8162+
\begin{itemdescr}
8163+
\pnum
8164+
\returns
8165+
\tcode{a.allocate_at_least(n)} if that expression is well-formed;
8166+
otherwise, \tcode{\{a.allocate(n), n\}}.
8167+
\end{itemdescr}
8168+
81398169
\rSec2[default.allocator]{The default allocator}
81408170

81418171
\rSec3[default.allocator.general]{General}
@@ -8167,6 +8197,7 @@
81678197
constexpr allocator& operator=(const allocator&) = default;
81688198

81698199
[[nodiscard]] constexpr T* allocate(size_t n);
8200+
[[nodiscard]] constexpr allocation_result<T*> allocate_at_least(size_t n);
81708201
constexpr void deallocate(T* p, size_t n);
81718202
};
81728203
}
@@ -8215,6 +8246,37 @@
82158246
but not that of any of the array elements.
82168247
\end{itemdescr}
82178248

8249+
\indexlibrarymember{allocate_at_least}{allocator}%
8250+
\begin{itemdecl}
8251+
[[nodiscard]] constexpr allocation_result<T*> allocate_at_least(size_t n);
8252+
\end{itemdecl}
8253+
8254+
\begin{itemdescr}
8255+
\pnum
8256+
\mandates
8257+
\tcode{T} is not an incomplete type\iref{basic.types}.
8258+
8259+
\pnum
8260+
\returns
8261+
\tcode{allocation_result<T*>\{ptr, count\}},
8262+
where \tcode{ptr} is a pointer to
8263+
the initial element of an array of \tcode{count} \tcode{T} and
8264+
$\tcode{count} \geq \tcode{n}$.
8265+
8266+
\pnum
8267+
\throws
8268+
\tcode{bad_array_new_length}
8269+
if $\tcode{numeric_limits<size_t>::max() / sizeof(T)} < \tcode{n}$,
8270+
or \tcode{bad_alloc} if the storage cannot be obtained.
8271+
8272+
\pnum
8273+
\remarks
8274+
The storage for the array is obtained by calling \tcode{::operator new},
8275+
but it is unspecified when or how often this function is called.
8276+
This function starts the lifetime of the array object,
8277+
but not that of any of the array elements.
8278+
\end{itemdescr}
8279+
82188280
\indexlibrarymember{deallocate}{allocator}%
82198281
\begin{itemdecl}
82208282
constexpr void deallocate(T* p, size_t n);
@@ -8223,9 +8285,18 @@
82238285
\begin{itemdescr}
82248286
\pnum
82258287
\expects
8226-
\tcode{p} is a pointer value obtained from \tcode{allocate()}.
8288+
\begin{itemize}
8289+
\item
8290+
If \tcode{p} is memory that was obtained by a call to \tcode{allocate_at_least},
8291+
let \tcode{ret} be the value returned and
8292+
\tcode{req} be the value passed as the first argument to that call.
8293+
\tcode{p} is equal to \tcode{ret.ptr} and
8294+
\tcode{n} is a value such that $\tcode{req} \leq \tcode{n} \leq \tcode{ret.count}$.
8295+
\item
8296+
Otherwise, \tcode{p} is a pointer value obtained from \tcode{allocate}.
82278297
\tcode{n} equals the value passed as the first argument
8228-
to the invocation of allocate which returned \tcode{p}.
8298+
to the invocation of \tcode{allocate} which returned \tcode{p}.
8299+
\end{itemize}
82298300

82308301
\pnum
82318302
\effects

0 commit comments

Comments
 (0)