logo

C++ Keywords - explicit

Implicit conversions allow an object of one type (called the source type) to be used where a different type (called the destination type) is expected, such as when passing an int argument to a function that takes a double parameter.

The explicit keyword can be applied to a constructor or a conversion operator, to ensure that it can only be used when the destination type is explicit at the point of use, e.g., with a cast. This applies not only to implicit conversions, but to list initialization syntax:

class Foo {
  explicit Foo(int x, double y);
  ...
};

void Func(Foo f);
Func({42, 3.14}); // Error

Best Practice

TL;DR: Most constructors should be explicit.

  • Implicit Conversions: Prior to C++11, the explicit keyword was primarily used for single-argument constructors to prevent implicit type conversions. However, with C++11, the explicit keyword's meaning expanded to include multi-parameter constructors. This means that multi-parameter constructors can also be involved in implicit conversions, which is why the guidance should be applied to multi-argument constructors as well.
  • Preventing Unintentional Conversions: The explicit keyword is used to prevent unintentional type conversions. When a constructor is marked as explicit, it requires the programmer to explicitly specify the constructor call, which helps to avoid accidental implicit conversions. This is especially useful when a constructor can be called with multiple arguments that could be interpreted in multiple ways.
  • Explicit Construction: When a constructor is marked as explicit, it forces the use of the constructor syntax (e.g., ClassName(arg1, arg2)) rather than relying on implicit conversion. This makes the code more explicit and less prone to ambiguity, especially when the arguments could be interpreted as different types.
  • Copy Initialization: In C++11, explicit became meaningful for copy-initialization from braced lists, such as when calling a function void f(std::pair) with f({1, 2}) or when initializing a variable bad with std::vector bad = {"hello", "world"}.
  • Value vs. Recipe: The explicit keyword should be used when the constructor is not simply creating a value, but rather a recipe for a value. For example, if the arguments are not the value of the newly created object, the constructor should be explicit.