【发布时间】:2011-09-09 05:01:35
【问题描述】:
我试图弄清楚如何在 const 方法中从映射中返回值,但我偶然发现了 gcc 4.6 中映射的 at() 方法。
当我查看这个时,我意识到它是非标准的:
C++ map access discards qualifiers (const)
但它肯定比 find() 方法更简洁。我想知道 C++11 是否已经纠正了这一点 - 新标准的地图部分是 at() 吗?
【问题讨论】:
我试图弄清楚如何在 const 方法中从映射中返回值,但我偶然发现了 gcc 4.6 中映射的 at() 方法。
当我查看这个时,我意识到它是非标准的:
C++ map access discards qualifiers (const)
但它肯定比 find() 方法更简洁。我想知道 C++11 是否已经纠正了这一点 - 新标准的地图部分是 at() 吗?
【问题讨论】:
是的。 std::map 在 C++11 中有一个 at 成员函数,其规范如下 (23.4.4.3/9):
T& at(const key_type& x); const T& at(const key_type& x) const;返回: 一个对映射类型的引用,对应于
*this中的x。抛出:如果不存在此类元素,则为
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");
}
或者,如果您有一个支持右值引用和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 代码的子集。)
【讨论】:
UniqueAssociativeContainer 是模板参数的更好名称(UniqueAssociativeContainerOrUniqueUnorderedAssociativeContainer 有点太笨拙了 :-O)。关键是,除了 C++ 标准库容器之外,还有其他容器满足容器概念的要求,并且它们应该可以与通用代码中的 C++ 标准库容器互换。依赖于新 at 的代码无法使用其他容器。