Date: Wed, 8 Jul 2026 12:19:07 +0200
wow, thanks Eyal to highlight it, what a coincidence.
In my case, it came out from standard careful read
while I was forwarding existing information for an
internal upskill for colleagues.
That said, let me provide answers to Marcin and you, in turn.
For Marcin:
> I recall this discussion but was this even in single inhrace case too?
> And if in this simple case the compiler does multiple moves, could this
means
> that the code created by compiler correctly move all data?
> Like my example in my prev email, I did multiple moves but as a whole
> it only "move data" once and does not override it after that.
> And this idiom can be safely nested as only most outer function
> have data and rest do empty moves.
I would say, the point is not whether the compiler can do it simply or not
in special cases. The point is that the standard keeps it "unspecified"
in any case. To me, it means we cannot use it at all. This links to another
part of your statement:
< I did multiple moves but as a whole it only "move data" once
and does not override it after that >
First, this would be a contradiction. If the operation is done multiple
times,
then it must move from the source multiple times. Or, at least, the current
wording from the standard should be clarified. Such a kind of 'final effect
as if the move happens exactly once' was my hope when I first posted the
question in https://lists.isocpp.org/std-discussion/2026/07/3430.php
Pls, note that in https://lists.isocpp.org/std-discussion/2026/07/3431.php
we had Ville who made this try: https://godbolt.org/z/PK3GEav13
showing that the move is really performed twice.
Also, I tried something like this: https://godbolt.org/z/rzq5cq5fK
(and no problems, instead, with the constructors:
https://godbolt.org/z/orMY9xvh5 )
showing that moving twice destroys the information in both source and
destination. This means that the compilers implementation are really
following the standard wording about the option to perform the move
multiple times.
About you, Eyal, I see interesting in the stack overflow thread this
information:
there was a change from C++11 to C++14.
Before C++14, we had that in case of virtual base classes the move
assign.op.
was defined as deleted, and we had the 'unspecified' only for the copy
assign.op.
In my opinion, this should be reverted. It makes no sense at all to
unspecifiy
for the move, which means we cannot use it at all.
About the cases when it would be complicated to get or not a "good" implicit
definition... again, I am not necessarily asking for that. It would be an
option,
but I prefer to have it defined as deleted, simple and consistent.
We are having a hot time for C++ around safety.
IMHO, having an implicit definition that cannot guarantee at all not to
destroy
the information, means to go against safety.
No guarantee there means useless. More, it means dangerous, because we
might have it both implicitly declared and implicitly defined.
We should not bet by relying that the compiler will do it correctly, at
least
for our simple class. If the standard keeps it unspecified, we risk, and
even if
we verify our current compiler works well, who assures for next version or
with
a different toolchain ? We lose portability.
The change from C++11 to C++14 was here:
https://cplusplus.github.io/CWG/issues/1806.html
where they also refer
https://cplusplus.github.io/CWG/issues/1402.html
stating that the additional change 1806 was a consequence
of the resolution for the issue 1402.
However, 1402 mainly focused on the non-triviality for constructors
and assignment operators, and THEN also worked on virtual base
scenarios.
So, one the one hand, 1402 avoided to uselessly have too many
cases with deleted move operations, but in my opinion it finally
led to reach the opposite... too many cases with an implicit definition.
I am convinced once more that the "unspecified" for move assign.op.
in case of virtual base classes is dangerous. An alternative should
be placed in the standard. The simplest: define as deleted.
Others are possible, but this is matter of discussion.
Mauro.
Il giorno mar 7 lug 2026 alle ore 18:01 Eyal Rozenberg <eyalroz1_at_[hidden]>
ha scritto:
> Hello Mauro and all,
>
> I'll first say that I believe the discussion actually stems from a
> StackOverflow question (I) asked a few days ago about this same subject:
>
> https://stackoverflow.com/q/79974174/1593077
>
> and the discussion it evoked.
>
> Whether that's actually the case or just a coincidence - I believe,
> Mauro, that the merited specification change is the opposite of what you
> suggest. AFAICT, the compiler can very well generate a valid
> move-assignment operator, which moves the virtual base class exactly once.
>
> To illustrate this, consider the following 4-class diamond pattern, used
> also in the SO question:
>
> A , with custom move assignment
> B : public virtual A , with defaulted move-assignment
> C : public virtual A , with defaulted move-assignment
> D : public virtual B, public virtual C , with defaulted move-assignment
>
> Generating a move assignment for B (resp. C) is obvious: Apply the move
> assignment of A, then move-assign each of the remaining data members of
> B (resp. C).
>
> Generating a move assignment for _D_ is a little more sophisticated, but
> still rather straightforward: Given the fact that B and C are defaulted,
> and the compiler know they comprise of move-assigning A and
> move-assigning B\A (resp. C\A) - it can generate a move-assignment which
> does the following:
>
> move-assign A
> move-assign B\A
> move-assign C\A
>
> and Bob's your uncle. The order of B before C is the order of listing of
> parent classes in the class definition.
>
> An SO user at the link raised a concern about consistency with
> auto-generated copy-assignment; and others claimed that this complicates
> the language too much, etc. I have not found those arguments very
> convincing; but of course - I am not well-versed in the standard enough
> to make a call, and maybe I've missed something. Have I?
>
> Eyal
>
>
>
>
> On 07/07/2026 11:11, mauro russo via Std-Discussion wrote:
> > Following the message in
> > https://lists.isocpp.org/std-discussion/2026/07/3433.php <https://
> > lists.isocpp.org/std-discussion/2026/07/3433.php>
> >
> > I really believe that the behavior from [class.copy.assign]-p(12.3) :
> > It is unspecified whether subobjects representing virtual base
> > classes are assigned more than once by the implicitly-defined
> > copy/move assignment operator
> >
> > has room for modification proposals, related to the move assign.op.
> >
> > Pls, anyone to clearly state it would not make sense to go
> > for a step further in https://isocpp.org/std/submit-a-proposal <https://
> > isocpp.org/std/submit-a-proposal>
> >
> > I might propose to go for define as deleted the move assign.op.
> > as I don't see ways to work around it but not using at all.
> > Providing an unspecified definition that most likely "clears"
> > the objects state (moving twice or more), is totally unfair to me.
> > Other cases of unspecified have a workaround, as for example
> > the undetermined sequence in arguments evaluation for a
> > function call -> just don't rely on any in the rest of the code.
> > But here, I see nothing beyond just not using it.
> > If not an undefined behaviour, why not being consistent and
> > include in the rules to define as deleted ?
> > Other options are possible (to me) but not keep it 'unspecified'.
> >
> > Kind regards.
> > Mauro.
> >
>
>
In my case, it came out from standard careful read
while I was forwarding existing information for an
internal upskill for colleagues.
That said, let me provide answers to Marcin and you, in turn.
For Marcin:
> I recall this discussion but was this even in single inhrace case too?
> And if in this simple case the compiler does multiple moves, could this
means
> that the code created by compiler correctly move all data?
> Like my example in my prev email, I did multiple moves but as a whole
> it only "move data" once and does not override it after that.
> And this idiom can be safely nested as only most outer function
> have data and rest do empty moves.
I would say, the point is not whether the compiler can do it simply or not
in special cases. The point is that the standard keeps it "unspecified"
in any case. To me, it means we cannot use it at all. This links to another
part of your statement:
< I did multiple moves but as a whole it only "move data" once
and does not override it after that >
First, this would be a contradiction. If the operation is done multiple
times,
then it must move from the source multiple times. Or, at least, the current
wording from the standard should be clarified. Such a kind of 'final effect
as if the move happens exactly once' was my hope when I first posted the
question in https://lists.isocpp.org/std-discussion/2026/07/3430.php
Pls, note that in https://lists.isocpp.org/std-discussion/2026/07/3431.php
we had Ville who made this try: https://godbolt.org/z/PK3GEav13
showing that the move is really performed twice.
Also, I tried something like this: https://godbolt.org/z/rzq5cq5fK
(and no problems, instead, with the constructors:
https://godbolt.org/z/orMY9xvh5 )
showing that moving twice destroys the information in both source and
destination. This means that the compilers implementation are really
following the standard wording about the option to perform the move
multiple times.
About you, Eyal, I see interesting in the stack overflow thread this
information:
there was a change from C++11 to C++14.
Before C++14, we had that in case of virtual base classes the move
assign.op.
was defined as deleted, and we had the 'unspecified' only for the copy
assign.op.
In my opinion, this should be reverted. It makes no sense at all to
unspecifiy
for the move, which means we cannot use it at all.
About the cases when it would be complicated to get or not a "good" implicit
definition... again, I am not necessarily asking for that. It would be an
option,
but I prefer to have it defined as deleted, simple and consistent.
We are having a hot time for C++ around safety.
IMHO, having an implicit definition that cannot guarantee at all not to
destroy
the information, means to go against safety.
No guarantee there means useless. More, it means dangerous, because we
might have it both implicitly declared and implicitly defined.
We should not bet by relying that the compiler will do it correctly, at
least
for our simple class. If the standard keeps it unspecified, we risk, and
even if
we verify our current compiler works well, who assures for next version or
with
a different toolchain ? We lose portability.
The change from C++11 to C++14 was here:
https://cplusplus.github.io/CWG/issues/1806.html
where they also refer
https://cplusplus.github.io/CWG/issues/1402.html
stating that the additional change 1806 was a consequence
of the resolution for the issue 1402.
However, 1402 mainly focused on the non-triviality for constructors
and assignment operators, and THEN also worked on virtual base
scenarios.
So, one the one hand, 1402 avoided to uselessly have too many
cases with deleted move operations, but in my opinion it finally
led to reach the opposite... too many cases with an implicit definition.
I am convinced once more that the "unspecified" for move assign.op.
in case of virtual base classes is dangerous. An alternative should
be placed in the standard. The simplest: define as deleted.
Others are possible, but this is matter of discussion.
Mauro.
Il giorno mar 7 lug 2026 alle ore 18:01 Eyal Rozenberg <eyalroz1_at_[hidden]>
ha scritto:
> Hello Mauro and all,
>
> I'll first say that I believe the discussion actually stems from a
> StackOverflow question (I) asked a few days ago about this same subject:
>
> https://stackoverflow.com/q/79974174/1593077
>
> and the discussion it evoked.
>
> Whether that's actually the case or just a coincidence - I believe,
> Mauro, that the merited specification change is the opposite of what you
> suggest. AFAICT, the compiler can very well generate a valid
> move-assignment operator, which moves the virtual base class exactly once.
>
> To illustrate this, consider the following 4-class diamond pattern, used
> also in the SO question:
>
> A , with custom move assignment
> B : public virtual A , with defaulted move-assignment
> C : public virtual A , with defaulted move-assignment
> D : public virtual B, public virtual C , with defaulted move-assignment
>
> Generating a move assignment for B (resp. C) is obvious: Apply the move
> assignment of A, then move-assign each of the remaining data members of
> B (resp. C).
>
> Generating a move assignment for _D_ is a little more sophisticated, but
> still rather straightforward: Given the fact that B and C are defaulted,
> and the compiler know they comprise of move-assigning A and
> move-assigning B\A (resp. C\A) - it can generate a move-assignment which
> does the following:
>
> move-assign A
> move-assign B\A
> move-assign C\A
>
> and Bob's your uncle. The order of B before C is the order of listing of
> parent classes in the class definition.
>
> An SO user at the link raised a concern about consistency with
> auto-generated copy-assignment; and others claimed that this complicates
> the language too much, etc. I have not found those arguments very
> convincing; but of course - I am not well-versed in the standard enough
> to make a call, and maybe I've missed something. Have I?
>
> Eyal
>
>
>
>
> On 07/07/2026 11:11, mauro russo via Std-Discussion wrote:
> > Following the message in
> > https://lists.isocpp.org/std-discussion/2026/07/3433.php <https://
> > lists.isocpp.org/std-discussion/2026/07/3433.php>
> >
> > I really believe that the behavior from [class.copy.assign]-p(12.3) :
> > It is unspecified whether subobjects representing virtual base
> > classes are assigned more than once by the implicitly-defined
> > copy/move assignment operator
> >
> > has room for modification proposals, related to the move assign.op.
> >
> > Pls, anyone to clearly state it would not make sense to go
> > for a step further in https://isocpp.org/std/submit-a-proposal <https://
> > isocpp.org/std/submit-a-proposal>
> >
> > I might propose to go for define as deleted the move assign.op.
> > as I don't see ways to work around it but not using at all.
> > Providing an unspecified definition that most likely "clears"
> > the objects state (moving twice or more), is totally unfair to me.
> > Other cases of unspecified have a workaround, as for example
> > the undetermined sequence in arguments evaluation for a
> > function call -> just don't rely on any in the rest of the code.
> > But here, I see nothing beyond just not using it.
> > If not an undefined behaviour, why not being consistent and
> > include in the rules to define as deleted ?
> > Other options are possible (to me) but not keep it 'unspecified'.
> >
> > Kind regards.
> > Mauro.
> >
>
>
Received on 2026-07-08 10:19:23
