Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ Constructor Overload Resolution with Multiple Inheritance

I've got this short snippet of code that I'd like to get a bit more information about as to why overload resolution is picking one constructor over another. Here's the code in question:

#include <iostream>

struct Base
{

};

struct Other
{
    Other(const Other&)
    {
        std::cout << "Copy Constructor\n";
    }
    Other(const Base&)
    {
        std::cout << "Custom Constructor\n";
    }
};

struct Derived : public Base, public Other
{
    Derived() :
        Other(*this)
    {

    }
};

int main()
{
    Derived derived;    // Prints "Copy Constructor"

    system("pause");
    return 0;
}

I'm assuming there's a section in the C++ Standard that defines the copy constructor as a better match than user defined constructors*? My assumption otherwise was that if no rule favoring the copy constructor existed, then the compiler would either go by the order of inheritance (as with the order of construction with multiple inheritance) or just give me an ambiguous constructor call error. However, reversing the order in which Derived inherits from Base and Other doesn't change the output, which leads me to believe that my initial guess about copy constructors being favored is correct. Could anyone point me to the rule that determines the behavior I'm seeing?

* I checked cppreference.com's Overload Resolution page, but I didn't see any rule listed there that would explain the behavior I'm seeing (though I'm not completely fluent in Standardese, so I could have easily missed it).

like image 800
DFS_Shadow Avatar asked Nov 07 '22 19:11

DFS_Shadow


1 Answers

The reason that the code snippet in question compiles is due to non-standard conforming behavior from Visual Studio (I'm currently using VS2017.3 Preview, which compiles the code without errors even with the /permissive- flag). Below is the error emitted by GCC and Clang:

GCC

Error(s):
source_file.cpp: In constructor ‘Derived::Derived()’:
source_file.cpp:25:20: error: call of overloaded ‘Other(Derived&)’ is ambiguous
         Other(*this)
                    ^
source_file.cpp:16:5: note: candidate: Other::Other(const Base&)
     Other(const Base&)
     ^
source_file.cpp:12:5: note: candidate: Other::Other(const Other&)
     Other(const Other&)
     ^

Clang

Error(s):
source_file.cpp:25:9: error: call to constructor of 'Other' is ambiguous
        Other(*this)
        ^     ~~~~~
source_file.cpp:12:5: note: candidate constructor
    Other(const Other&)
    ^
source_file.cpp:16:5: note: candidate constructor
    Other(const Base&)
    ^
1 error generated.

Error output taken from http://rextester.com/.

like image 151
DFS_Shadow Avatar answered Nov 15 '22 06:11

DFS_Shadow