I don't understand why the code below prints struct Value
instead of int
(which implies the conversion constructor is converting to Value
instead of int
). (Visual C++ 2012)
Why is this happening? Why does the compiler completely ignore the Value(int)
constructor?
#include <iostream>
#include <type_info>
using namespace std;
struct Value { Value(int) { } };
struct Convertible
{
template<class T>
operator T() const
{ throw typeid(T).name(); }
};
int main()
{
try { Value w((Convertible())); }
catch (char const *s) { cerr << s << endl; }
}
Even more bizarre is this (this time it's C++11 only, on GCC 4.7.2):
#include <iostream>
#include <typeinfo>
using namespace std;
struct Value
{
Value(Value const &) = delete;
Value(int) { }
};
struct Convertible
{
template<class T>
operator T() const
{ throw typeid(T).name(); }
};
int main()
{
try { Value w((Convertible())); }
catch (char const *s) { cerr << s << endl; }
}
Which gives:
source.cpp: In function 'int main()':
source.cpp:21:32: error: call of overloaded 'Value(Convertible)' is ambiguous
source.cpp:21:32: note: candidates are:
source.cpp:9:3: note: Value::Value(int)
source.cpp:8:3: note: Value::Value(const Value&) <deleted>
If the copy constructor is deleted, then why is there any ambiguity?!
Conversion Operators in C++ C++ supports object oriented design. So we can create classes of some real world objects as concrete types. Sometimes we need to convert some concrete type objects to some other type objects or some primitive datatypes. To make this conversion we can use conversion operator.
A constructor that is not declared with the specifier explicit and which can be called with a single parameter (until C++11) is called a converting constructor.
A conversion constructor is a single-parameter constructor that is declared without the function specifier explicit . The compiler uses conversion constructors to convert objects from the type of the first parameter to the type of the conversion constructor's class.
Conversion constructor in C++? The constructors are used to construct objects of a class. Sometimes constructors may take some arguments, or sometimes it does not take arguments. When a constructor takes only one argument then this type of constructors becomes conversion constructor.
In the first example Visual Studio is incorrect; the call is ambiguous. gcc in C++03 mode prints:
source.cpp:21:34: error: call of overloaded 'Value(Convertible)' is ambiguous
source.cpp:21:34: note: candidates are:
source.cpp:9:5: note: Value::Value(int)
source.cpp:6:8: note: Value::Value(const Value&)
Recall that a copy constructor is implicitly defaulted. The governing paragraph is 13.3.1.3 Initialization by constructor [over.match.ctor]:
When objects of class type are direct-initialized [...], overload resolution selects the constructor. For direct-initialization, the candidate functions are all the constructors of the class of the object being initialized.
In the second example, deleted functions participate equally in overload resolution; they only affect compilation once overloads have been resolved, when a program that selects a deleted function is ill-formed. The motivating example in the standard is of a class that can only be constructed from floating-point types:
struct onlydouble {
onlydouble(std::intmax_t) = delete;
onlydouble(double);
};
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