2012-03-05 4 views
5

У меня есть класс, который содержит картуПерегруженный оператор не бросать исключения

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

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

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

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

Был ли я запущен в некоторых ограничениях на C++ или я делаю что-то неправильно?

--edit:

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

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

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

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

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

+0

Лично я бы поставил 'find' и сравнение по разным линиям – pkit

+1

Это (возможно) не причиной вашей проблемы, но вам нужно будет вернуться по значению - вы не можете вернуть ссылку на временную. –

+0

@pkit И инициализировать 'it' в заявлении, которое его определило. –

ответ

2

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

В случае, когда вам нужно различное поведение в зависимости от использования, традиционное решениепредназначено для предоставления прокси-сервера. Ваш 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); 
    } 
}; 
+0

+1 для прокси. Шаблон «Proxy» часто игнорируется, хотя это, вероятно, один из самых изменчивых моделей, которые я видел. –