You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[BUG] The meaning of operator= with multiple non-this parameters #451
More generally, writing = always invokes an operator= (in fact for a Cpp2-authored type, and semantically for a Cpp1-authored type). This avoids the Cpp1 inconsistency that "writing = calls operator=, except when it doesn't" (such as in a Cpp1 variable initialization). Conversely, operator= is always invoked by =.
Besides #449, further integration is also the objective of #368, and perhaps also of #409. #321 is another such issue, but = (...) is intended for an std::initializer_list parameter.
As you can see below, cppfront currently lowers to
a Cpp1 assignment operator with multiple arguments, which is ill-formed.
In order for this to work, it'd have to be lowered to a Cpp1 cpp2_assign overload
(inspired from the C++ standard library containers assign member functions):
build/_cppfront/main.cpp:9:16: error: overloaded 'operator=' must be a binary operator (has 3 parameters)
public: auto operator=(auto const& x, auto const& y) -> t& ;
^
In order for this to work, it'd have to be lowered to a Cpp1 cpp2_assign overload
(inspired from the C++ standard library containers assign member functions):
I considered just using assign, which means
Cpp2's = works for the container's assign,
but Cpp2 claims assign as a member.
Here's where it gets contentious with #321.
Cpp2 a = (x, y) would have to choose between
Cpp1 a = {x, y} and
Cpp1 a.cpp2_assign(x, y).
I thought about proposing to emit an assignment operator with a parameter such that a = {x, y} always works.
The use of braces would be consistent with emitted initialization,
as = would reject narrowing conversions whether it's a definite first assignment or not.
(See https://cpp2.godbolt.org/z/sarMKvnGo generate braces for initialization
and https://cpp2.godbolt.org/z/EcrnEh75v error due to narrowing braces in assignment).
First, the current operator=: (out this, x: i8) = { } (single non-this parameter) narrows on non definite first assignment
(as opposed to using narrowing-preventing braces, see https://cpp2.godbolt.org/z/e8ojnYPc4).
Next, consider if #321 were fixed. a = {x, y} would happen to work, but actually construct a t and then move-assign to a
(see https://cpp2.godbolt.org/z/4s64rnsEd, after changing the type to avoid narrowing braces).
The fact is that Cpp2 has the opportunity for its = to be both correct and efficient.
Rather than relying on a = {x, y} happening to work
(when the user writes a operator=: (out this, x: i8, y: i8) = { } [two non-this parameters]),
it could explicitly emit an operator=/cpp2_assign
like it does for operator=: (out this, x: i8) = { } (single non-this parameter).
However, the proposal to
emit an assignment operator with a parameter such that a = {x, y} always works
means it'd be ambiguous with the constructor generated from operator= with out this.
So it seems like a binary choice between
Here's where it gets contentious with #321.
Cpp2 a = (x, y) would have to choose between
Cpp1 a = {x, y} and
Cpp1 a.cpp2_assign(x, y).
I thought about proposing to emit an assignment operator with a parameter such that a = {x, y} always works.
So it seems like a binary choice between
efficient a.cpp2_assign(x, y) and
narrowing-preventing braces a = {x, y}.
The alternative is to combine these two monsters
to emit a.cpp2_assign({x, y}) (see https://cpp2.godbolt.org/z/e9313Ebr9).
But for a = (x, y) to also work for #321,
something else is necessary, like the UFCS macro overload resolution.
If that's acceptable, I'd learn towards preferring the more performant cpp2_assign.
Program returned: 0
Capacity before proposed assignment: 100
Capacity after proposed assignment: 100
Capacity before current assignment: 100
Capacity after current assignment: 13
In order for this to work, it'd have to be lowered to a Cpp1 cpp2_assign overload
(inspired from the C++ standard library containers assign member functions):
I considered just using assign, which means
Cpp2's = works for the container's assign,
but Cpp2 claims assign as a member.
Unfortunately, for ranges, the containers use assign_range.
Activity
JohelEGP commentedon May 11, 2023
I considered just using
assign, which means=works for the container'sassign,assignas a member.I thought about proposing to emit an assignment operator with a parameter such that
a = {x, y}always works.The use of braces would be consistent with emitted initialization,
as
=would reject narrowing conversions whether it's a definite first assignment or not.(See https://cpp2.godbolt.org/z/sarMKvnGo generate braces for initialization
and https://cpp2.godbolt.org/z/EcrnEh75v error due to narrowing braces in assignment).
However, if the user were to write both
then non definite first assignment becomes ambiguous (as seen at https://cpp2.godbolt.org/z/GWsKPMzYf).
This also highlights two facts.
First, the current
operator=: (out this, x: i8) = { }(single non-thisparameter) narrows on non definite first assignment(as opposed to using narrowing-preventing braces, see https://cpp2.godbolt.org/z/e8ojnYPc4).
Next, consider if #321 were fixed.
a = {x, y}would happen to work, but actually construct atand then move-assign toa(see https://cpp2.godbolt.org/z/4s64rnsEd, after changing the type to avoid narrowing braces).
The fact is that Cpp2 has the opportunity for its
=to be both correct and efficient.Rather than relying on
a = {x, y}happening to work(when the user writes a
operator=: (out this, x: i8, y: i8) = { }[two non-thisparameters]),it could explicitly emit an
operator=/cpp2_assignlike it does for
operator=: (out this, x: i8) = { }(single non-thisparameter).However, the proposal to
means it'd be ambiguous with the constructor generated from
operator=without this.So it seems like a binary choice between
a.cpp2_assign(x, y)anda = {x, y}.JohelEGP commentedon May 11, 2023
The alternative is to combine these two monsters
to emit
a.cpp2_assign({x, y})(see https://cpp2.godbolt.org/z/e9313Ebr9).But for
a = (x, y)to also work for #321,something else is necessary, like the UFCS macro overload resolution.
If that's acceptable, I'd learn towards preferring the more performant
cpp2_assign.JohelEGP commentedon May 11, 2023
Unfortunately, braces prevent deduction
(see #312 and https://cpp2.godbolt.org/z/41fqv6YqP).
So perhaps we should just lose the braces
(see https://cpp2.godbolt.org/z/fKc9Kve1r and the output warnings).
JohelEGP commentedon May 12, 2023
Here's an example of current vs. proposed (https://cpp2.godbolt.org/z/5vosWPW5n):
Unfortunately, for ranges, the containers use
assign_range.