проверка границ в операторе [] (int i) - PullRequest
0 голосов
/ 29 ноября 2011

Как мне вернуть недопустимый объект обратно пользователю, когда он запрашивает элементы вне границы в контейнере. Я не бросаю исключения.

Я закодировал свой собственный шаблон хэш-таблицы

template <class Type1, class Type2> class wqHashTable
{

    public:
    template <class Type1, class Type2> 
        Type2& wqHashTable<Type1, Type2>::operator[](int idx) const
        {
            if (goodId(idx))
            {
                return m_pValue[idx];
            }
            else
            {
                Type2* tValue = new Type2[1];   //TODO: How do we handle errors?

                return tValue[0];
            }
        }
    }

Ответы [ 6 ]

2 голосов
/ 29 ноября 2011

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

boost::optional<Type2&> operator[](int idx) const
{
    if(good_idx(idx)
      return boost::optional<Type2&>(m_pValue[idx]);
    return boost::optional<Type2&>(); // uninitialized
}

Телефонный код:

boost::optional<the_type&> opt_ret = your_table[idx];
if(ret){
  the_type& ret = *opt_ret; // for convenience
  // valid idx, use ret
}

Или вы можете следовать схеме std::vector и просто вернуть m_pValue[idx], хорошо это или плохо, и предоставить метод .at(int idx), который выполняет проверку границ (и выдает исключение, еслипроверка не пройдена).

В общем, нет никаких причин не использовать исключения.Другие ответы уже подробно изложены на этом.

1 голос
/ 29 ноября 2011

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

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

1 голос
/ 29 ноября 2011

Либо throw (ИДК, почему вы не хотите этого делать) или return NULL;.

Другой вариант - это иметь какое-то поле типа ".thisIsErrorObject"возвращаемый тип;таким образом, вы можете создавать объекты, используя сами коды ошибок.

0 голосов
/ 29 ноября 2011
template <class Type1, class Type2> class wqHashTable
{
    Type2 INVALID_ELEMENT;
public:
    bool last_access_valid;

    template <class Type1, class Type2> 
    Type2& wqHashTable<Type1, Type2>::operator[](int idx) const
    {
        last_access_valid = goodId(idx);
        if (last_access_valid )
            return m_pValue[idx];
        else 
            return INVALID_ELEMENT;
    }
}

Для этого требуется Type2 для создания по умолчанию, что не является гарантией, которую вы всегда будете иметь, но довольно распространено.Вызывающий может проверить значение last_access_valid.

. Если вы собираетесь использовать такую ​​вещь, как last_access_valid, я настоятельно рекомендую класс, подобный тому, который я разместил на https://stackoverflow.com/a/8088357/845092, чтобы гарантироватьУтверждение, что это проверяется каждый раз, поэтому вы не можете случайно забыть.В этом случае тип last_access_valid будет ForceCheckError<bool>, а если вызывающий не проверит его, он будет assert.

0 голосов
/ 29 ноября 2011

Я бы assert(goodId(idx)); и return m_pValue[idx];.

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

Иначе, возможно, использовать конструкции стандартных ассоциативных контейнеров?

0 голосов
/ 29 ноября 2011

Если вы не хотите создавать исключения, вам нужно знать, что вы хотите сделать.Например, вы можете захотеть иметь предопределенный член, который будет возвращать ссылку в случае выхода за пределы.Я не думаю, что вы хотите сделать что-либо здесь new, но опять же, это зависит от ваших намерений.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...