Reputation: 9173
I have a small code like this:
class A {
public:
A() {
std::cout << "ctor\n";
}
A(int i = 5) {
std::cout << "ctor -> v\n";
}
virtual ~A() {
std::cout << "dtor\n";
}
};
int main() {
A a;
}
It is is obvious that this code won't compile because A
's constructor is ambiguous. I wonder if there is anyway to disambiguate this code by manually selecting which constructor to call. I don't want to pass default value in order to disambiguate function call (which is a obvious approach). I just want to know if there is any other way or not.
Upvotes: 4
Views: 570
Reputation: 170094
Without changing the constructor definitions there is no way in standard C++ to disambiguate the call.
Your options for clearing the ambiguity are to either remove the default argument, or to add a "dummy" tag argument to the first constructor.
constexpr struct default_tag_t{} default_tag{};
///
A(default_tag_t) {
std::cout << "ctor\n";
}
Which makes the first constructor uniquely callable with
A a(default_tag);
Upvotes: 3
Reputation: 6490
Actually I think it is not possible. I was looking into getting to call the mangled name but I was not able to generate those mangled names. For this you have to expose the class to the binary interface by adding a __declspec(dllexport)
and after you do this, even compiling the class is no longer possible (regardless of calling any ctor):
#include <iostream>
class __declspec(dllexport) A {
public:
A() {
std::cout << "ctor\n";
}
A(int i = 5) {
std::cout << "ctor -> v\n";
}
virtual ~A() {
std::cout << "dtor\n";
}
};
int main() {
// A a;
}
Output was
1>------ Build started: Project: ConsoleApplicationMangled, Configuration: Debug Win32 ------
1>ConsoleApplicationMangled.cpp
1>e:\temp\ConsoleApplicationMangled\ConsoleApplicationMangled\ConsoleApplicationMangled.cpp(5,30): error C2668: 'A::A': ambiguous call to overloaded function
1>e:\temp\ConsoleApplicationMangled\ConsoleApplicationMangled\ConsoleApplicationMangled.cpp(11,5): message : could be 'A::A(int)'
1>e:\temp\ConsoleApplicationMangled\ConsoleApplicationMangled\ConsoleApplicationMangled.cpp(7,5): message : or 'A::A(void)'
1>e:\temp\ConsoleApplicationMangled\ConsoleApplicationMangled\ConsoleApplicationMangled.cpp(18,2): message : while trying to match the argument list '()'
1>e:\temp\ConsoleApplicationMangled\ConsoleApplicationMangled\ConsoleApplicationMangled.cpp(18,2): message : This diagnostic occurred in the compiler generated function 'void A::__dflt_ctor_closure(void)'
1>Done building project "ConsoleApplicationMangled.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
Upvotes: 1
Reputation: 51845
The only way that I can see (if you really need both constructors) is to remove the default value of the argument in the second constructor and make the 'default' constructor call that:
class A {
public:
A() : A(5) {
std::cout << "ctor\n";
}
A(int i) {
std::cout << "ctor -> v\n";
}
virtual ~A() {
std::cout << "dtor\n";
}
};
But then, for the default ('empty') instatiation, the body code for both constructors will execute.
Upvotes: 1