Consider the following piece of code:
#include <iostream>
struct C
{
C()
{
std::cout << "C()\n";
}
explicit C(const C&)
{
std::cout << "C(const C&)\n";
}
operator int()
{
std::cout << "int()\n";
return 1;
}
C(int)
{
std::cout << "C(int)\n";
}
};
int main()
{
C c1;
std::cout << '\n';
C c2 = c1;
std::cout << '\n';
C c3(c1);
}
Both g++
and clang
give the following output:
C()
int()
C(int)
C(const C&)
Doesn't it break the rule saying that an implicit conversion sequence can consist of at most one user conversion?
This only compiles because you're initializing class C
with itself in the line C c2 = c1;
. If you had a class D
which behaves identically to C
and tried D d; C c = d;
, it wouldn't compile for the reason you stated: because the implicit conversion would require two user-defined conversions. Demonstation
The reason it compiles when using the same class is that copy-initialization (A x = y;
) behaves differently when y
is of type A
or derived from it. In that case, a converting constructor is selected and that constructor is then invoked with the argument y
, which may cause an implicit conversion. The constructor call itself is not part of the implicit conversion.
So in your code, the conversion sequence only contains one user-defined conversion: C
to int
, as the constructor C(int)
is called separately.
See C++14 8.5/17:
- If the initialization is direct-initialization, or if it is copy-initialization where the cv-unqualified version of the source type is the same class as, or a derived class of, the class of the destination, constructors are considered. The applicable constructors are enumerated (13.3.1.3), and the best one is chosen through overload resolution (13.3). The constructor so selected is called to initialize the object, with the initializer expression or expression-list as its argument(s).
- Otherwise (i.e., for the remaining copy-initialization cases), user-defined conversion sequences that can convert from the source type to the destination type or (when a conversion function is used) to a derived class thereof are enumerated [...]
Read more at http://en.cppreference.com/w/cpp/language/copy_initialization.
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