According to the C++ Core Guidelines, rule C.46:
By default, declare single-argument constructors explicit.
The reason is to avoid unintended conversions.
However, why is the explicit keyword recommended to avoid unintended conversions only for constructors with a single argument? Wouldn't implicit conversions with multiple arguments also be potentially problematic?
EDIT:
For example, in the code below, can't ComplexC and ComplexD be used for implicit conversion (see function calls below)? If so, wouldn't the rule apply to ComplexD as well?
class ComplexA { // example from C.46
public:
ComplexA(double r) {}
};
class ComplexB {
public:
explicit ComplexB(double r) {}
};
class ComplexC {
public:
ComplexC(double r, double i) {}
};
class ComplexD {
public:
explicit ComplexD(double r, double i) {}
};
void f_non_explicit(ComplexA a) {
std::cout << "Called f_non_explicit for ComplexA\n" ; }
void f_explicit(ComplexB b) {
std::cout << "Called f_explicit for ComplexB\n" ; }
void f_non_explicit(ComplexC c) {
std::cout << "Called f_non_explicit for ComplexC\n" ; }
void f_explicit(ComplexD d) {
std::cout << "Called f_explicit for ComplexD\n" ; }
int main()
{
ComplexA za = {10.7};
// ComplexB zb = {10.7}; // error: constructor is explicit in copy-initialization
ComplexC zc = {10.7, 11};
// ComplexD zd = {10.7, 11}; // error: constructor is explicit in copy-initialization
f_non_explicit({100.1}); // prints "Called f_non_explicit for ComplexA"
f_non_explicit({200.1, 300.1}); // prints "Called f_non_explicit for ComplexC"
// f_explicit({100.1}); // error: error: no matching function
// f_explicit({200.1, 300.1}); // error: error: no matching function
}
explicitwith a multi-argument constructor is to prevent unintended implicit conversions when using initializer lists. As several C++ luminaries have said, "C++: all the defaults are wrong." In my opinion, theexplicitshould have been the default behavior if not specified, andimplicitshould have been required to opt-in for converting constructor. Alas, that ship has sailed.