Перегруженный оператор не выбрасывает исключения - PullRequest
5 голосов
/ 05 марта 2012

У меня есть класс, который содержит карту

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 ");
  }
}

Я хочу, чтобы оно генерировало исключение, когда поле не существует на карте, поэтому программа не падает при неудачной загрузке, но, похоже, команда throw не работает с перегруженным оператором. бросок или улов игнорируются. Если я использую тот же код, но с общей функцией

Any& Map::get( const unsigned int field ) const
{
  //...

это работает.

Я столкнулся с каким-то ограничением c ++ или я что-то не так делаю?

- РЕДАКТИРОВАТЬ:

Я запустил отладчик и, к моему удивлению, код даже не выполняется, другой метод делает

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;
}

и сбой происходит из-за форсированного утверждения на Any, которое пытается преобразовать неинициализированную переменную. Этот метод, вероятно, используется для вставок на карту, например

Map a;
a[3] = "foo";

Так что, я думаю, у меня нет способа провести различие, когда оператор используется в атрибуции или при получении, а использование этого оператора крайне небезопасно для получения

1 Ответ

2 голосов
/ 05 марта 2012

Повторное редактирование: разрешение перегрузки обычно учитывает только аргументы, а не использование. Если у вас есть const и неконстантная функция с другими идентичными подписями, неконстантный будет выбран, если возможно (например, вызывается для неконстантного объекта).

В случае, если вы хотите различного поведения в зависимости от использования, Традиционное решение заключается в предоставлении прокси. Ваш Map класс будет содержит две функции get и set, а неконстантный operator[] вернет прокси, который выглядит примерно так:

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 );
    }
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...