This article explains when we should use the qualifier explicit and when we shouldn't.

Avoids undesirable conversions

Normally, if a constructor can be called with one argument, it can be used as a conversion. For instance, if you define a constructor, F::F(Foo name), and then pass a string to this function that expects a Foo, this constructor will be called and convert the string into a Foo and will pass the Foo to your function for you. This can be convenient but is also a source of trouble when things get converted and new objects created without you meaning them to. Declaring a constructor explicit prevents it from being invoked implicitly as a conversion.

In addition to single-parameter constructors, this also applies to constructors where every parameter after the first has a default value, e.g., F::F(Foo name, int id = 42).

We require all constructors that are callable with a single argument to be explicit. Always put explicit in front of such constructors in the class definition: explicit Foo(string name);

Exceptions

Copy and move constructors are exceptions: they should not be explicit. Classes that are intended to be transparent wrappers around other classes are also exceptions. Such exceptions should be clearly marked with comments.

Finally, constructors that take only a std::initializer_list may be non-explicit. This permits construction of your type from a braced initializer list, as in an assignment-style initialization, function argument, or return statement. For example:

MyType m = {1, 2}; 
MyType MakeMyType() { return {1, 2}; }
TakeMyType({1, 2});