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