Search code examples
c++c++11constructorexplicitmultiple-arguments

When to use explicit specifier for multi-argument constructors?


I have recently learned about the explicit specifier.

Suppose we have:

f( W, W, W );

Now if we do

f( 42, 3.14, "seven" );

The compiler will attempt the following implicit conversions:

f( W(42), W(3.14), W("seven") );

If we have defined matching constructors for W, namely:

W(int);
W(double);
W(std::string);

...it will succeed.

However, if we make the first one explicit:

explicit W(int);

... this disables the implicit conversion.

You would now have to write:

f( W(42), 3.14, "seven" );

i.e. it is forcing you to explicitly state the conversion

Now on to the question:

It is possible to write:

explicit W(int,int); // 2 arguments!

This compiles!

But I can't see any corresponding scenario that might require this syntax.

Can anyone provide a minimal example?


Solution

  • If your constructor is explicit and the class doesn't supply a non-explicit constructor taking initializer_list<T>, then you cannot copy-list-initialize an instance.

    W w = {1,2}; // compiles without explicit, but not with
    

    Simple live example

    #include <iostream>
    
    class A
    {
    public:
       explicit A(int, int) {}
    };
    
    class B
    {
    public:
        B(int, int) {}
    };
    
    int main()
    {
       B b = {1,2};
       A a = {1,2};
    }
    

    Quotes from standard:

    8.5/16

    — If the initializer is a (non-parenthesized) braced-init-list, the object or reference is list-initialized (8.5.4).

    8.5.4/3

    List-initialization of an object or reference of type T is defined as follows: ...

    Otherwise, if T is a class type, constructors are considered. The applicable constructors are enumerated and the best one is chosen through overload resolution (13.3, 13.3.1.7). If a narrowing conversion (see below) is required to convert any of the arguments, the program is ill-formed.