Does making a constructor having multiple arguments explicit
have any (useful) effect?
Example:
class A {
public:
explicit A( in
Up until C++11, yeah, no reason to use explicit
on a multi-arg constructor.
That changes in C++11, because of initializer lists. Basically, copy-initialization (but not direct initialization) with an initializer list requires that the constructor not be marked explicit
.
Example:
struct Foo { Foo(int, int); };
struct Bar { explicit Bar(int, int); };
Foo f1(1, 1); // ok
Foo f2 {1, 1}; // ok
Foo f3 = {1, 1}; // ok
Bar b1(1, 1); // ok
Bar b2 {1, 1}; // ok
Bar b3 = {1, 1}; // NOT OKAY
The excellent answers by @StoryTeller and @Sneftel are the main reason. However, IMHO, this makes sense (at least I do it), as part of future proofing later changes to the code. Consider your example:
class A {
public:
explicit A( int b, int c );
};
This code doesn't directly benefit from explicit
.
Some time later, you decide to add a default value for c
, so it becomes this:
class A {
public:
A( int b, int c=0 );
};
When doing this, you're focussing on the c
parameter - in retrospect, it should have a default value. You're not necessarily focussing on whether A
itself should be implicitly constructed. Unfortunately, this change makes explicit
relevant again.
So, in order to convey that a ctor is explicit
, it might pay to do so when first writing the method.
Here's my five cents to this discussion:
struct Foo {
Foo(int, double) {}
};
struct Bar {
explicit Bar(int, double) {}
};
void foo(const Foo&) {}
void bar(const Bar&) {}
int main(int argc, char * argv[]) {
foo({ 42, 42.42 }); // valid
bar({ 42, 42.42 }); // invalid
return 0;
}
As you can easily see, explicit
prevents from using initializer list alongside with bar
function bacause the constructor of struct Bar
is declared as explicit
.
You'd stumble upon it for brace initialization (for instance in arrays)
struct A {
explicit A( int b, int c ) {}
};
struct B {
B( int b, int c ) {}
};
int main() {
B b[] = {{1,2}, {3,5}}; // OK
A a1[] = {A{1,2}, A{3,4}}; // OK
A a2[] = {{1,2}, {3,4}}; // Error
return 0;
}