Take a simple class wrapping an int,
struct Foo {
int x;
} f;
and a class that holds a Foo and that can be converted to it,
struct Bar {
Foo f;
operator Foo&() {
return f;
}
operator Foo const&() const {
return f;
}
Bar& operator=(Bar const&) = default;
} b;
What part of the standard, if any, makes this invalid
b = f;
instead of being equivalent to this?
static_cast<Foo&>(b) = f;
(I'm not saying it should, nor that it would be normal, expected or anything like that.)
Here I read that
For the built-in assignment operators, conversions of the left operand are restricted as follows:
- [...]
- no user-defined conversions are applied to the left operand to achieve a type match with the left-most parameter of a built-in candidate.
For all other operators, no such restrictions apply.
So am I misunderstanding the meaning of "built-in assignment operator" and the = in b = f is the built-in = to which that restriction applies?
Or is that = not the bult-in and so that restriction does not apply but the code is flawed for other reasons?
Paragraph 3 there describes the candidate set:
So for
b = f, our member candidates areb.operator=(f)and we have no non-member candidates.The paragraph that you cited talks about when the built-in candidates are viable, but built-in are those provided by the language (in [over.built]) - those could apply if your type is convertible to something like
int&. Those aren't relevant here.But in this case,
bis convertible toFoo&, and there's no mechanism here to considerFoo::operator=as a candidate. We only have the member candidates to consider, and only our own (Bar's) members - not arbitrary other types' members.