Saturday, August 8, 2009

Episode Five: Explicit is Better than Implicit

Type conversion allows one type to convert to another. In C++, they came in two flavours:
  • Conversion by construction: Constructors that can be called with a single argument are called converting constructors. This includes constructors with a single formal argument, as well as constructors with more than one argument that specifies default values. Implements conversion-from-type, intrusive on the destination type.
  • Conversion functions: Also called conversion operators, are member functions defined as `operator Type() [const]` (Note no result type defined). Implements conversion-to-type, intrusive on the source type.

Automatic conversion is believed to be too error prone. If an operator does not apply to a class but does apply unambiguously to one of its implicitly convertible types such operator will be called. When designing a phone number class it might make sense for its objects to automatically became integers, but what does adding them means? Such paths must be carefully forbidden by means of access rules.

Code which relies upon implicit type conversions may become broken when new classes or functions are added, when used in conjunction with overloaded functions. If a function f takes an object of type T1 which is convertible from char const*, it can be called as `f( "some text" )` since automatic conversion will create the appropiate T1 object from "some text" under the hood. However, if an overload for function f is later added with an argument of type T2, which is also convertible from char const*, suddenly the call becames ambiguous and will no longer compile.

When declarating constructors, the `explicit` specifier can be used to indicate that the constructor is merely a constructor and shall not be considered for implicit type conversions. For a practical example of why this is needed, consider std::vector's `explicit vector( size_type n )` constructor, which constructs a vector with n default constructed elements. Shall not this constructor specified as explicit, `std::vector<> v = 10;` will result in a vector of 10 elements. Even more, a function having `std::vector<> const&` as an argument would be callable with an integer! There is no `explicit` specifier for conversion operators (yet, but it will be part of C++0x).

Automatic type conversion should be used carefully. It’s excellent when it significantly reduces a coding task, but it’s usually not worth using gratuitously.

No comments:

Post a Comment