Karl said:
Creating such conversion operators needs to be done with
great care. By introducing them, you enable the compiler
to convert parameters even in cases where you don't want
them to happen. This is exactly the reason why eg. std::string
has no conversion operator to const char*, but a member function
c_str() instead.
To emphasize on that further.
Consider the following situation:
#include <iostream>
using namespace std;
class SpecialFloat
{
public:
SpecialFloat( float Val = 0.0f ) : m_Value( Val ) {};
float ToFloat() { return m_Value; }
friend SpecialFloat operator+( const SpecialFloat& lhs, const SpecialFloat& rhs );
private:
float m_Value;
};
SpecialFloat operator+( const SpecialFloat& lhs, const SpecialFloat& rhs )
{
return lhs.m_Value + rhs.m_Value;
}
int main()
{
SpecialFloat a( 1.0f );
float b;
b = ( a + 2.0f ).ToFloat();
}
All is well.
Then some clever programmer decides that the call of ToFloat is ugly, and that somebody
has to do something about it: introduce operator float():
#include <iostream>
using namespace std;
class SpecialFloat
{
public:
SpecialFloat( float Val = 0.0f ) : m_Value( Val ) {};
float ToFloat() { return m_Value; }
friend SpecialFloat operator+( const SpecialFloat& lhs, const SpecialFloat& rhs );
operator float() { return m_Value; }
private:
float m_Value;
};
SpecialFloat operator+( const SpecialFloat& lhs, const SpecialFloat& rhs )
{
return lhs.m_Value + rhs.m_Value;
}
int main()
{
SpecialFloat a( 1.0f );
float b;
b = a + 2.0f;
}
But now the whole thing no longer compiles.
Why?
Because the compiler now has to equally good ways to translate
b = a + 2.0f;
it could either
a) using the constructor, convert 2.0f to a SpecialFloat object and applying
the user defined operator+ on both SpecialFloat objects
or
b) convert a from SpecialFloat to an ordinary float by using the conversion
operator float() on a and using the builtin operator+ for floats.