Does "explicit" keyword have any effect on a default constructor? [duplicate]
Asked Answered
B

2

42

Is there a reason to use the explicit keyword for a constructor that doesn't take any arguments? Does it have any effect? I'm wondering because I just came across the line

explicit char_separator()

near the end of the page documenting boost::char_separator, but it's not explained any further there.

Ballyrag answered 21/7, 2011 at 11:32 Comment(5)
Not a dupe; this question is about a very specific corner case of the explicit keyword.Anastomosis
That's not a function, that's a constructor - see #121662Inflorescence
@larsmans Hard to tell without seeing some real exampleBostow
@VJo: check <boost/token_functions.hpp>, it's there.Anastomosis
@larsman If we are taking about char_separator, described in the link above (boost.org/doc/libs/1_47_0/libs/tokenizer/char_separator.htm), then it is a constructor, and this question is a duplicate.Bostow
D
8

Yes, it does have an effect.

Compare:

struct A
{
    A() {}
};

void foo(A) {}

int main()
{
    foo({}); // ok
}

and:

struct A
{
    explicit A() {}
};

void foo(A) {}

int main()
{
    foo({}); // error
}
Derk answered 3/5, 2022 at 19:20 Comment(1)
This is the correct answer starting with C++11. When asking the question back then, I was still using C++03, where brace initialization was not available. Boost was already one step ahead :)Ballyrag
M
16

Reading explanation of members :

explicit char_separator(const Char* dropped_delims,
                        const Char* kept_delims = "",
                        empty_token_policy empty_tokens = drop_empty_tokens)
explicit char_separator()

The explicit keyword for the 1st constructor requires explicit creation of objects of char_separator type. What does the explicit keyword mean in C++? covers the explicit keyword very well.

The explicit keyword for the 2nd constructor is a noise and is ignored.

EDIT

From the c++ standard :

7.1.2 p6 tells :

The explicit specifier shall be used only in declarations of constructors within a class declaration; see 12.3.1.

12.3.1 p2 tells :

An explicit constructor constructs objects just like non-explicit constructors, but does so only where direct-initialization syntax (8.5) or where casts (5.2.9, 5.4) are explicitly used. A default constructor may be an explicit constructor; such a constructor will be used to perform default-initialization or value-initialization (8.5). [Example:

class Z {
public:
explicit Z();
explicit Z(int);
// ...
};
Z a;               // OK: default-initialization performed
Z a1 = 1;          // error: no implicit conversion
Z a3 = Z(1);       // OK: direct initialization syntax used
Z a2(1);           // OK: direct initialization syntax used
Z* p = new Z(1);   // OK: direct initialization syntax used
Z a4 = (Z)1;       // OK: explicit cast used
Z a5 = static_cast<Z>(1); // OK: explicit cast used

—end example]

So, the default constructor with the explicit keyword is the same as without this keyword.

Macrospore answered 21/7, 2011 at 11:50 Comment(3)
"The explicit keyword for the 2nd constructor is a noise and is ignored." what?Gaige
This answer is wrong, at least when considering brace initialization in modern versions of C++. Proof: godbolt.org/z/zdNvTp (if the explicit keyword is removed, the code compiles).Tote
explicit affects whether certain initializations can be performed.Induration
D
8

Yes, it does have an effect.

Compare:

struct A
{
    A() {}
};

void foo(A) {}

int main()
{
    foo({}); // ok
}

and:

struct A
{
    explicit A() {}
};

void foo(A) {}

int main()
{
    foo({}); // error
}
Derk answered 3/5, 2022 at 19:20 Comment(1)
This is the correct answer starting with C++11. When asking the question back then, I was still using C++03, where brace initialization was not available. Boost was already one step ahead :)Ballyrag

© 2022 - 2024 — McMap. All rights reserved.