I've being reading the list of library changes proposed for C++23 and I'm quite curious about the std::out_ptr
and std::inout_ptr
(their _t
siblings). As far as I understand they are some kind of wrapper for smart pointers to be compatible with raw pointers, but I haven't managed to understand them yet. Maybe someone here is familiar with the proposal or may give a less ISO-like explanation or examples?
TL;DR - it is for simpler and more seemless interoperability between C out/inout pointer parameters and smart pointers
Longer answer
Let's separate the stuff. std::out_ptr
and std::inout_ptr
are functions used to create objects of type std::out_ptr_t
and std::inout_ptr_t
respectively. What are those types and functions for? Let's look at an example inspired by this (for simplicity I replaced generic argument with good ol' int
):
int foreign_resetter(int**);
auto up = std::make_unique<int>(5);
if (int ec = foreign_resetter(std::inout_ptr(up)) {
return ec;
}
As you see std::inout_ptr_t
created with std::inout_ptr
is passed to function taking pointer to pointer to the template argument of std::unique_ptr
. Before adding std::inout_ptr_t
interoperation with old C in-out pointer parameters was much more cumbersome and error prone. It would look more less like this:
int foreign_resetter(int**);
auto up = std::make_unique<int>(5);
int* up_raw = up.release();
if (int ec = foreign_resetter(&up_raw)) {
return ec;
}
up.reset(up_raw);
Differences out_ptr
vs inout_ptr
From the proposal P1132:
inout_ptr's semantics are exactly like out_ptr's, just with the additional requirement that it calls .release() on the smart pointer upon constructing the temporary inout_ptr_t.
This is because the foreign_resetter
might delete a pointer before setting a new one, calling .release()
reserves that behavior and can be safer. Use inout_ptr
if your pointer is already valid and allocated, and out_ptr
if the smart pointer is empty.
out_ptr
and inout_ptr
? –
Digitalize inout_ptr
version - it's actually more error-prone, since C APIs often don't guarantee the output is valid in case of an error. So you could end up with a garbage pointer in that case. –
Wylen up
can't be dereferenced in case of error, as we've return
ed away from it's scope –
Lymphangitis delete
a null pointer. If you have an api that is writing an invalid pointer value then it's not an appropriate api to call like this, and I'd argue it's a bug in the api. Well behaved apis either don't change the pointer, or write a null pointer there. –
Lymphangitis -1
, and the contents of strp
is undefined.") –
Wylen up.release()
in the error handler. I stand by my assertion that inventing an invalid pointer value out of nowhere is a bad api. From the link you gave, at least some implementations promise a valid pointer value even on error. It's also an api unsuitable for using with std::unique_ptr
in the first place, because it requires you free()
the pointer, not delete
it. –
Lymphangitis foreign_resetter
does either. It could very well allocate with new
. –
Wylen © 2022 - 2024 — McMap. All rights reserved.
void foo(SomeType**)
whereas we would expectstd::unique_ptr<SomeType> foo()
C++-API). – Ripstd::out_ptr_t
andstd::inout_ptr_t
(the latter is a bit more elaborate and contains an example) – Deathlike