I have a class that contains a map
Any& Map::operator[]( const unsigned int field ) const
{
try
{
iterator it;
if ((it = m_fields.find(field)) != m_fields.end())
return it->second;
throw std::runtime_error("Field " + boost::lexical_cast<std::string>(field) + " not found.");
}
catch(boost::bad_any_cast& )
{
throw std::runtime_error("Failed conversion field " + boost::lexical_cast<std::string>(field) + " using boost::any_cast ");
}
}
I want it to throw an exception when the field does not exists in the map so the program does not crash on a bad get, but the throw does not seem to work on the overloaded operator, the program crashes anyway so either the throw or the catch are being ignored. If I use the same code but with a common function
Any& Map::get( const unsigned int field ) const
{
//...
it works.
Did I ran in some c++ limitation or am I doing something wrong?
--EDIT :
I ran the debugger and to my surprise that code doesn't even execute, another method does
Any& Map::operator[]( const unsigned int field )
{
iterator it;
if ((it = m_fields.find(field)) == m_fields.end())
{
Any newValue;
m_fields[field] = newValue;
return m_fields[field];
}
return it->second;
}
and the crash occurs because of a boost assert on Any that tries to convert a uninitialized variable. This method is probably used on inserts on the map, like
Map a;
a[3] = "foo";
So I guess I have no way to differentiate when the operator is used on an atribution or on a get and the use of this operator is highly unsafe for gets
Re your edit: overload resolution generally only takes into account the arguments, not the use. If you have a const and a non-const function with otherwise identical signatures, the non-const will be chosen if possible (e.g. called on a non-const object).
In a case where you do want different behavior depending on the use, the
traditional solution is to provide a proxy. Your Map
class would
contain two functions get
and set
, and the non-const operator[]
would return a
proxy which looks something like:
class Proxy // member of Map
{
Map* myOwner;
int myIndex;
public:
Proxy( Map* owner, int index )
: myOwner( owner )
, myIndex( index )
{
}
void operator=( Any const& rhs ) const
{
myOwner->put( myIndex, rhs );
}
operator Any() const
{
return myOwner->get( myIndex );
}
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With