Anirban Sarkar Anirban Sarkar - 22 days ago 5
C++ Question

Overload Resolution: What is the role of explicit and the initialization syntax?

Suppose I have an immutable

String
class as follows:

#include <iostream>
#include <string>

class String
{
public:
explicit String(const char *Value) : Size(std::strlen(Value)), Value(new char[Size + 1])
{
std::memcpy(this->Value, Value, Size + 1);
std::cout << Value << ", novice." << Size << std::endl;
}
template <typename T, std::size_t N> String(const T (&Value)[N]) : Size(N - 1), Value(new char[N])
{
std::memcpy(this->Value, Value, N);
std::cout << Value << ", expert." << Size << std::endl;
}
~String()
{
delete[] Value;
}
private:
const std::size_t Size;
char *Value;
};

void main()
{
auto &s = "Welcome to C++";
String string = s;
String str {s};
String st(s);
return;
}


I want to know the role
explicit
plays and how the initialization syntax makes a difference when the constructor overload is chosen.




I understand that for
str
and
st
, I am explicitly calling the constructor that takes a pointer to
const char
, so they print out:

Welcome to C++, novice.
Welcome to C++, novice.


But I don't understand why for
string


Welcome to C++, expert.


is printed out. Please clarify how the overload is being selected.

Answer

With

String str {s};
String st(s);

The

explicit String(const char *Value)

The reason the pointer overload is chosen is because it is not templated. Both the pointer and the array constructors are considered as an exact match to s so it would be an ambiguity but since the array constructor is a template it is consider less of a match then the pointer constructor. Even if you removed the explicit the pointer overload would still be chosen.

Now with

String string = s;

explicit does matter because s is not a String. This means the compiler needs to implicitly convert it to one so it chooses the array constructor as it is an exact match and the only viable constructor as explicit constructors cannot be used in implicit conversions.

Comments