Anirban Sarkar Anirban Sarkar - 11 months ago 35
C++ Question

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

Suppose I have an immutable

class as follows:

#include <iostream>
#include <string>

class String
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;
delete[] Value;
const std::size_t Size;
char *Value;

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

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

I understand that for
, 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

Welcome to C++, expert.

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

Answer Source


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


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.