Является ли at () const аксессором для стандарта карт в C ++ 11? - PullRequest
8 голосов
/ 09 сентября 2011

Я пытался выяснить, как вернуть значение из карты в методе const, и я наткнулся на метод at () для карты в gcc 4.6.

Когда я посмотрел это, я понял, что это нестандартно:

Доступ к карте C ++ отменяет квалификаторы (const)

Но это, конечно, гораздо менее многословно, чем подход find (). Мне было интересно, исправил ли это C ++ 11 - это at () для части карты нового стандарта?

1 Ответ

17 голосов
/ 09 сентября 2011

Да.std::map имеет функцию-члена at в C ++ 11 со следующей спецификацией (23.4.4.3/9):

T&       at(const key_type& x);
const T& at(const key_type& x) const;

Возвращает: Ссылка наmapped_type, соответствующий x в *this.

Throws: Объект исключения типа out_of_range, если такого элемента нет.

Сложность: логарифмическая.

Обратите внимание, однако, что эта функция-член была специально добавлена ​​к std::map.Это не требуется более общим ассоциативным контейнером .Если вы пишете общий код, который требует некоторого ассоциативного типа контейнера, вы не можете использовать этот новый at.Вместо этого вы должны продолжать использовать find, который является частью концепции ассоциативного контейнера , или написать свой собственный помощник, не являющийся членом:

template <typename AssociativeContainer>
typename AssociativeContainer::mapped_type&
get_mapped_value(AssociativeContainer&                          container,
                 typename AssociativeContainer::key_type const& key)
{
    typename AssociativeContainer::iterator it(container.find(key));
    return it != container.end() ? it->second : throw std::out_of_range("key");
}

template <typename AssociativeContainer>
typename AssociativeContainer::mapped_type const&
get_mapped_value(AssociativeContainer const&                    container,
                 typename AssociativeContainer::key_type const& key)
{
    typename AssociativeContainer::const_iterator it(container.find(key));
    return it != container.end() ? it->second : throw std::out_of_range("key");
}

Или, если у вас естьреализация, которая поддерживает rvalue-ссылки и decltype, вам не нужно две перегрузки:

template <typename AssociativeContainer, typename Key>
auto get_mapped_value(AssociativeContainer&& container, Key const& key)
    -> decltype(std::declval<AssociativeContainer>().begin()->second)&
{
    auto const it(container.find(key));
    return it != container.end() ? it->second : throw std::out_of_range("key");
}

(или что-то похожее; одна забавная вещь в C ++ 11 состоит в том, что ни у двух компиляторов нет одинаковыхошибки и все они, кажется, принимают несколько разные подмножества действительного и недействительного кода C ++ 11.

...