C++ Logo


Advanced search

Re: [std-proposals] Relocation in C++

From: Edward Catmur <ecatmur_at_[hidden]>
Date: Sat, 24 Sep 2022 16:40:04 +0100
On Thu, 22 Sept 2022 at 18:48, S├ębastien Bini <sebastien.bini_at_[hidden]>

> On Wed, Sep 21, 2022 at 4:51 PM Edward Catmur <ecatmur_at_[hidden]>
> wrote:
>> std::decompose would need to be magic (compiler-implemented), to be able
>> to call destructors on nonrelocated subobjects, so it would be able to
>> bypass access checks anyway; it might be possible to implement it in the
>> language with reflection once that arrives, but it's widely expected that
>> reflection will also allow bypassing access checks.
>> So the danger is actually that std::decompose would be too powerful and
>> allow arbitrary code to access private/protected base subobjects of
>> unrelated class types; but this can be prevented by requiring the compiler
>> to look at the context of the call to determine whether the caller is
>> allowed to access that base class subobject.
> I fail to see the real danger here. Sure we may extract private/protected
> subobjects, but the source object we extracted them from is destroyed. So
> it's not like we can mess with it. We simply get independant objects that
> have no relationship with one another, which is guaranteed by the fact that
> the object we extracted them from has no user-provided constructors and
> destructor.

A tuple class is highly likely to have user-provided constructors, even if
its destructor is defaulted; indeed, a class that needs to make use of this
facility will almost certainly not be aggregate constructible, otherwise it
would be able to use aggregate structured binding. For example, std::tuple
has user-provided constructors, so this facility would have to accept class
types with user-provided constructors. So there is a definite danger that
this could be abused to access private/protected bases of a class type that
uses those bases to maintain invariants, and by doing so break those

Sorry, I meant to use decltype(auto) with no parameter packs. More like:
> void vector<T>::push_back_impl(decltype(auto) val);
> void vector<T>::push_back(T const& val) { push_back_impl(reloc val); }
> void vector<T>::push_back(T&& val) { push_back_impl(reloc val); }
> void vector<T>::push_back(T val) { push_back_impl(reloc val); }

Yes, that would certainly be legal and a valid implementation technique.

Every operator token is currently a keyword; there are four identifiers
>> with special meaning (final, override, import and module) but they are not
>> operators.
>> The problem with having it as an operator that is not a keyword is
>> parsing; is `reloc x;` a discarded-value relocation expression (destroying
>> x) or is it the declaration of a variable `x` with type `reloc`? If `reloc`
>> is not allowed as an identifier, then that's basically the same as making
>> it a keyword.
> Fair point. When I first thought of this reloc operator, I considered
> using a new symbol instead. Like `$x`, `_at_x`, or `>x`, etc... instead of
> `reloc x`. However I do find `reloc` to be better than a symbol: first, it
> clearly conveys the intent. Second, it is visually more eye-catching, which
> helps when reading code. I reckon it's important to quickly see where
> relocation happens as it ends the scope of variables.

Yes, but adding a keyword that could be already in use as an identifier is
fraught, and could become an obstacle. An alternative is to construct a
sequence of punctuation tokens that cannot currently appear in a program,
as was done for spaceship; with that in mind, you might propose something
like `<~< x`?

FWIW, C has historically handled this by introducing new keywords with
>> _Reserved names and requiring code to opt-in to friendlier names by
>> #including a header that implicitly #defines the new keyword to the
>> _Reserved name. But that's not been workable in C++ since so much of our
>> code is in headers and so it would leak into code that includes those
>> headers. Perhaps modules would make it possible to opt-into a new keyword.
> I figured a simple #if __cplusplus >= 202900L would do the job?

That's enough for new code that wants to be backwards compatible, but it
doesn't solve the problem of old code that may already use `reloc` as an

Received on 2022-09-24 15:40:17