Copy initialization vs direct initialization RRS feed

  • Question

  • Hi,

    I was  going through the page Copy vs direct intialization

    In that page there is one example, as below

    #include <iostream>
    struct B;
    struct A { 
      operator B();
    struct B { 
      B() { }
      B(A const&) { std::cout << "<direct> "; }
    A::operator B() { std::cout << "<copy> "; return B(); }
    int main() { 
      A a;
      B b1(a);  // 1)
      B b2 = a; // 2)
    // output: <direct> <copy>

    When compiled on VS2015 compiler it is giving output as <copy> <copy> but on other compilers it is <direct> <copy>.

    Is direct and copy initialization is compiler dependent thing ?

    Please let me know .



    Thanks, Jafar

    • Edited by Jafar Kumarkiri Wednesday, March 28, 2018 5:39 PM hyper link added
    Wednesday, March 28, 2018 5:38 PM

All replies

  • Well, for a start, Visual Studio 2017 outputs <direct> <copy>. This seems to agree with other compilers.

    But anyway. If what you wrote is true for this exact code then I would be surprised if it does try to copy the first one. The syntax of:

    B b1(a);

    Is basically calling the constructor, so overload resolution should prefer the direct match of B(const A &) over B(const B&) and operator B(), (or B() and operator B() with copy elision).

    For the second one, I can't remember what the standard says on this. But the interesting thing is that A::operator B is only winning out because of the constness, or lack thereof. This actually makes it a better match because constructing B with a non const B::B() returned from A::operator B() is a better match.

    Interestingly, if you do one of two things, the compiler actually starts throwing compiler errors.

    For example, if you change B::B(const A&) to B::B(A&) then this will evaluate to the same as A::operator B() and will be found ambiguous for copy initialisation. The same is true if you leave B::B(const A&) as it is and change A::operator B() to A::operator B() const.

    So no, this isn't a compiler dependent thing, overload resolution should be pretty consistent. But maybe because Visual Studio 2017 has more C++ 17 features available that it is coming up with the same output as others. Because the others that you tried were Clang, probably 5 or 6, and GCC, probably 6 or 7 right? These have had some of the newer C++ 17 features in for longer than Visual C++.

    This is a signature. Any samples given are not meant to have error checking or show best practices. They are meant to just illustrate a point. I may also give inefficient code or introduce some problems to discourage copy/paste coding. This is because the major point of my posts is to aid in the learning process.

    • Proposed as answer by Baron Bi Thursday, March 29, 2018 6:25 AM
    Wednesday, March 28, 2018 10:26 PM
  • Visual Studio 2017 outputs <direct> <copy>.

    Yes, provided that conformance mode is enabled. If you upgrade from Visual Studio 2015 you may have to change this setting manually.
    Thursday, March 29, 2018 10:36 AM