Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is the at() const accessor for map standard in C++11?

Tags:

c++

c++11

map

stl

I was trying to figure out how to return a value from a map in a const method and I stumbled on the at() method for map in gcc 4.6.

When I looked this up I realized it was non-standard:

C++ map access discards qualifiers (const)

But it sure is a whole lot less verbose than the find() approach. I was wondering if the C++11 has rectified this - is at() for map part of the new standard?

like image 512
daj Avatar asked Sep 09 '11 05:09

daj


1 Answers

Yes. std::map has an at member function in C++11 with the following specification (23.4.4.3/9):

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

Returns: A reference to the mapped_type corresponding to x in *this.

Throws: An exception object of type out_of_range if no such element is present.

Complexity: logarithmic.

Note however that this member function has been added specifically to std::map. It is not required by the more general associative container requirement. If you are writing generic code that requires some associative container type, you can't use this new at. Instead, you should continue to use find, which is part of the associative container concept, or write your own non-member helper:

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

Or, if you have an implementation that supports rvalue references and decltype, you don't need two overloads:

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

(Or something close to that; one fun thing about C++11 is that no two compilers have the same bugs and all seem to accept slightly different subsets of valid--and invalid--C++11 code.)

like image 120
James McNellis Avatar answered Nov 03 '22 08:11

James McNellis