I've recently read somewhere (can't remember where) about using braces to allow multiple user-defined conversions, but there seems to be a difference between conversion by constructor and conversion by conversion method that I don't understand.
Consider:
#include <string>
using ::std::string;
struct C {
C() {}
};
struct A {
A(const string& s) {} // Make std::string convertible to A.
operator C() const { return C(); } // Makes A convertible to C.
};
struct B {
B() {}
B(const A& a) {} // Makes A convertible to B.
};
int main() {
B b;
C c;
// This works.
// Conversion chain (all thru ctors): char* -> string -> A -> B
b = {{"char *"}};
// These two attempts to make the final conversion through A's
// conversion method yield compiler errors.
c = {{"char *"}};
c = {{{"char *"}}};
// On the other hand, this does work (not surprisingly).
c = A{"char *"};
}
Now, I may be misinterpreting what the compiler is doing, but (based on the above and additional experimentation) it seems to me that it's not considering conversions by conversion-method. Reading through Sections 4 and 13.3.3.1 of the standard, however, I wasn't able to find a clue why this is. What is the explanation?
Update
Here's another interesting phenomenon I'd like explained. If I add
struct D {
void operator<<(const B& b) {}
};
and in main
:
D d;
d << {{ "char *" }};
I get an error, but if instead I write d.operator<<({{ "char *" }});
it works fine.
Update 2
Looks like Section 8.5.4 in the standard may hold some answers. I'll report my findings.
There is one user conversion possible.
In b = {{"char *"}};
we actually do
b = B{{"char*"}}; // B has constructor with A (and a copy constructor not viable here)
so
b = B{A{"char*"}}; // One implicit conversion const char* -> std::string
in c = {{"const char*"}}
, we try
c = C{{"char *"}}; // but nothing to construct here.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With