Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ implicit conversions with brace initializers

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.

like image 455
Ari Avatar asked May 27 '16 11:05

Ari


1 Answers

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.
like image 53
Jarod42 Avatar answered Oct 21 '22 13:10

Jarod42