C++ keyword of the day: explicit
Suppose we have the following class:
struct Foo
{
int m_i;
Foo(int const &i)
{
m_i = i;
}
operator int()
{
return m_i;
}
bool operator==(Foo const &foo)
{
return foo.m_i == m_i;
}
};
This class is a wrapper for ints. It allows you to transparently substitute Foos with ints in normal operations. This way you can use Foos like ints with additional meta data attached.
We also implement the normal operators (== in this example) so that we can operate on 2 Foos as if we were using 2 ints,
The constructor allows the compiler to convert an int to a Foo, and the typecast allows it to convert a foo to an int. This can be a problem. Consider the following use case:
if(foo == 1)
cout << "foo == 1" << endl;
Which will cause the following ambiguity error:
error C2666: 'Foo::operator ==' : 2 overloads have similar conversionscould be 'bool Foo::operator ==(const Foo &)' or 'built-in C++ operator==(int, int)' while trying to match the argument list '(Foo, int)'
To get out of this situation without removing either the constructor or the type cast, we can use the keyword explicit like this:
struct Foo
{
explicit Foo(int const &i){ } //details omitted
};
Now there is only one conversion path left: Foo to int.
It also makes it impossible to use implicit conversion during an assignment but you can also implement an assignment operator.
You lose the ability to implicitly convert an int to a Foo at construction time. You also lose the convenience of having ints silently being converted to Foos, but perhaps that is not so bad from a design point of view because that might introduce subtle bugs.