6

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?

P i
  • 29,020
  • 36
  • 159
  • 267
  • 2
    Part of this might be just for the sake of consistency, since multi-parameter functions may also have defaults, e.g. `explicit W(int,int=0);`. – Rufflewind Dec 25 '14 at 09:59

1 Answers1

12

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.

P i
  • 29,020
  • 36
  • 159
  • 267
ForEveR
  • 55,233
  • 2
  • 119
  • 133
  • Re-phrasing my previous comment: maybe the mention of `initializer_list` makes the answer confusing. But I think it is correct. – juanchopanza Dec 25 '14 at 09:00
  • When you say "implicit constructor", you mean "constructor not declared with the `explicit` keyword", and that does make sense, but when I read it, I think of implicitly generated constructors that are not declared by the user. (In your example, `A`'s copy constructor, for instance.) I don't know if "implicit constructor" is a generally accepted term the way you're using it, but it's not one I've come across before. –  Dec 25 '14 at 09:42