get should return only on
success| Document #: | D3857R0 |
| Date: | 2025-10-02 19:46 EDT |
| Project: | Programming Language C++ |
| Audience: |
LEWG |
| Reply-to: |
Pablo Halpern <phalpern@halpernwightsoftware.com> |
Should a value-retrieval function that returns a disengaged
optional on lookup failure be called
get? This question was briefly
debated in discussion of [P3091R4], which introduces just such a
function. In this paper, I try to take a principled approach to this
question. My conclusion is that a successful return from
get should imply a successful
retrieval of a value, and that a function that indicates failure through
the normal return value should be called something else. This paper
makes two, somewhat independent, proposals: 1) Rename the
get functions in P3091 to
lookup, and 2) have a general LEWG
policy for using get as a function
name.
R0 (2025-10 pre-Kona mailing)
[P3091R3] was approved by LEWG during the
June 2025 meeting in Sofia. It proposes new
get member functions in
std::map,
std::unordered_map,
and std::flat_map,
which return a std::optional<value_type&>.
The return value is engaged if the specified key is found within the map
and disengaged otherwise.
The use of a special, “empty”, return value (e.g., a null pointer,
disengaged optional, or erroneous
expected) is a break from the
typical pattern for get functions,
both within the Standard Library and in the wider programming world.
Within the Working Paper, member and nonmember
get functions for
unique_ptr,
shared_ptr,
tuple,
variant,
reference_wrapper,
subrange,
basic_format_string,
basic_format_args1,
and future do not return values that
can indicate failure; either they can never fail when called within
contract or they indicate failure other than by a normal return (e.g.,
they exit via an exception). The understood meaning of
get in all of these contexts is
“retrieve something that the user believes is retrievable.” The only
exceptions to this interface rule within the Standard Library are in
locale facets and
istream, where the retrieved value
is not communicated via the return value at all, but rather via a
pass-by-reference parameter. The idiosyncratic uses of
get in
locale and
istream are arguably poor exemplars
for designing new interfaces.
It was pointed out in the LEWG discussion of [P3091R4] that the proposed interface for
get is inconsistent with other uses
of get. Although unique_ptr::get
and shared_ptr::get
sometimes return
nullptr, it
was pointed out that the null value in these cases indicate a
successful retrieval of a value that happens to be a null
pointer, and is thus unrelated to the use of
optional in P3091. At the time, we
had not performed thorough review of
get in the working paper, and
minimal time was allocated to the discussion in a reasonable attempt to
avoid endless bike-shedding. An LEWG poll in Sophia on 2025-06-19 kept
the status-quo as of [P3091R3]:
POLL: Rename
.getto.lookup
SF
|
F
|
N
|
A
|
SA
|
|---|---|---|---|---|
| 1 | 3 | 6 | 2 | 6 |
The consensus against the change was tepid, at best. Furthermore, based on subsequent discussions and the research presented above, I, as the author of P3091, would change my vote from neutral to strongly in favor. The Proposals below would reverse this decision for P3091 and establish a general naming policy, in the hopes of avoiding unintuitive and inconsistent interfaces in the Standard.
This paper contains two proposals that can, and should, be polled independently. In particular, the proposed change to P3091 can be accepted even if the formal policy is not accepted or is deferred for modification and further discussion.
Rename the new get member
functions for map-like containers in the latest version of P3091 to
lookup. Note: [P3091R4] was forwarded to LWG at the
Sophia meeting, but has not been reviewed as of this date).
When adding a new function, the name
get shall be reserved for a function
that retrieves an object (or reference to an object) and whose normal
(non-exceptional, non-terminating) return implicitly indicates that the
object was successfully retrieved. A function that potentially returns a
not-found or not-available status, regardless of whether such a status
indicates an error, should be named something other than
get (e.g.,
lookup,
fetch,
get_if, etc.).