Constructors we should not make explicit
- We should not make copy (and move) constructors explicit as they do not perform conversions.
- Default constructors with no parameters as we usually use them for implicit conversion of
{}. - Constructors with multiple arguments as usually they are not candidates for conversions.
If we prefer, we can make option 2 and 3 as explicit.
Constructors we should make explicit
We should make single argument constructors explicit. However, there are cases when it is useful to have single-argument constructors non-explicit:
- When the conversion is not expensive such as for fundamental types as arguments.
- When the argument value is semantically equivalent to the constructed object.
Consider the example provided in this note, Int(int) can be made non-explicit as printInt(5) and printInt(Int) are semantically equivalent and conversion is inexpensive.
Now, consider the following program:
void printString(std::string s)
{
std::cout << s << "\n";
}
printString("hello world"sv); // throws errorstd::string constructor taking string view as argument is explicit and so the program fails. Although string view and std::string are semantically equivalent but conversion from string view to std::string is expensive.
On the other hand, std::string_view constructor taking std::string is non-explicit as they are semantically equivalent and conversion is inexpensive. For example,
void printString(std::string_view sv)
{
std::cout << sv << "\n";
}
printString("hello world"s);