C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Let constructor know if object is const or volatile

From: Edward Catmur <ecatmur_at_[hidden]>
Date: Fri, 29 Sep 2023 13:15:17 -0500
On Fri, 29 Sept 2023 at 03:08, Frederick Virchanza Gotham via Std-Proposals
<std-proposals_at_[hidden]> wrote:

> On Thu, Sep 28, 2023 at 12:05 PM Sebastian Wittmeier wrote:
> >
> > So you are asking for a way to know at runtime inside a constructor,
> whether the constructed object is const or non-const?
> > Like an implicit parameter? Not ABI compatible, performance cost.
> > Or at compile-time? Then the constructor would have to be a template to
> generate two functions.
> > It is not supported by the current standard.
> > As alternative you could use two different factory functions instead.
>
>
> There are a few possibilities for implementing this (and for the time
> being I'll ignore the problem of breaking ABI). I'm gonna use x86_64
> Linux SystemV as a sample platform.
>
> Possibility 1) Pass a hidden parameter to the constructor (e.g. put it
> in the RDI register and move everything else down one place). The
> hidden argument could be 0 for non-const non-volatile, 1 for const
> non-volatile, 2 for non-const volatile, and 3 for non-const
> non-volatile, and then inside the constructor, we could have:
>
> Monkey::Monkey(void)
> {
> if ( std::this_is_const() ) DoSomething();
> }
>
> This would work fine but it would mean a change to the ABI for calling
> the constructor.
>
> Possibility 2) Instead of passing a hidden parameter to the function,
> have a global thread-local variable to denote the constness and
> volatileness of the current object being constructed. The syntax for
> this would be the same:
>
> Monkey::Monkey(void)
> {
> if ( std::this_is_const() ) DoSomething();
> }
>
> This however would not alter the calling convention for invoking the
> constructor. The compiler would just have to make sure to set the
> global thread-local variable properly before invoking the constructor.
>
> Possibility 3) Have an implicit type '_This_t' defined within the body
> of the constructor. Of course, types cannot change at runtime, and so
> the distinction would have to be made at compile-time, meaning that
> each constructor would have four copies. So when we write the
> following:
>
> Monkey::Monkey(void)
> {
> if ( std::is_const_v(std::remove_pointer_t<_This_t>) )
> DoSomething();
> }
>
> It gets compiled to four separate funtions:
>
> Monkey::Monkey(void)
> {
> typedef Monkey *_This_t;
> if ( std::is_const_v(std::remove_pointer_t<_This_t>) )
> DoSomething();
> }
>
> Monkey::Monkey(void)
> {
> typedef Monkey const *_This_t;
> if ( std::is_const_v(std::remove_pointer_t<_This_t>) )
> DoSomething();
> }
>
> Monkey::Monkey(void)
> {
> typedef Monkey volatile *_This_t;
> if ( std::is_const_v(std::remove_pointer_t<_This_t>) )
> DoSomething();
> }
>
> Monkey::Monkey(void)
> {
> typedef Monkey const volatile *_This_t;
> if ( std::is_const_v(std::remove_pointer_t<_This_t>) )
> DoSomething();
> }
>
> This would then beg the question: If the constructor contains a static
> variable, is there just one copy of that variable shared between the
> four implementations, or is there four separate variables? If the
> answer to this question were 1, then we would have to consider what
> happens if you write the following:
>
> Monkey::Monkey(void)
> {
> static std::vector<_This_t> myvec;
>
> if ( std::is_const_v(std::remove_pointer_t<_This_t>) )
> DoSomething();
> }
>
> In the above snippet, the variable 'myvec' cannot be shared between
> the four implementations of the constructor. Perhaps in this instance
> we could stipulate:
> 'Inside a constructor, the type of any static variable cannot be
> dependant upon _This_t'.
>
> When it comes to the initialisation of a static-duration variable
> which is shared between the four implementations of the constructor,
> well the four implementations will share a common 'once_flag' for this
> purpose to ensure the variable only gets initialised once.
>

Why not propose overloading the constructor on an explicit object parameter?

Monkey::Monkey(this Monkey& self);
Monkey::Monkey(this Monkey const& self);

But you still haven't provided motivation.

Received on 2023-09-29 18:15:30