【问题标题】:Is the at() const accessor for map standard in C++11?是 C++11 中地图标准的 at() const 访问器吗?
【发布时间】:2011-09-09 05:01:35
【问题描述】:

我试图弄清楚如何在 const 方法中从映射中返回值,但我偶然发现了 gcc 4.6 中映射的 at() 方法。

当我查看这个时,我意识到它是非标准的:

C++ map access discards qualifiers (const)

但它肯定比 find() 方法更简洁。我想知道 C++11 是否已经纠正了这一点 - 新标准的地图部分是 at() 吗?

【问题讨论】:

    标签: c++ stl map c++11


    【解决方案1】:

    是的。 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 代码的子集。)

    【讨论】:

    • 我会说所有编译器都在接近 C++11,但这可能是我乐观的自我:)
    • [挑剔]。 'at' 方法不仅被添加到 std::map 中,还被添加到 std::unordered_map 中。这是仅有的两个使用这种方法真正有意义的标准容器。此外,您的代码不仅适用于 AssociateveContainers,而且适用于 UnorderedAssociateveContainers,但 set 和 unordered_set 除外,而且对于 multimap 和 unordered_multimap 几乎没有意义。
    • @Konstantin:是的,也许UniqueAssociativeContainer 是模板参数的更好名称(UniqueAssociativeContainerOrUniqueUnorderedAssociativeContainer 有点太笨拙了 :-O)。关键是,除了 C++ 标准库容器之外,还有其他容器满足容器概念的要求,并且它们应该可以与通用代码中的 C++ 标准库容器互换。依赖于新 at 的代码无法使用其他容器。
    • @Matthieu:我不知道...... Visual C++ 2010 接受了这个答案中的代码,但我未能击败 g++ 4.6 提交。我有一个相当大的爱好代码库,它利用了 C++0x 特性;它可以用 Visual C++ 编译,但我不能用 g++ 编译它,因为有两个错误(一个涉及在类模板中捕获 lambda,另一个涉及模板实例化失败)或 clang(它根本不支持 lambda)。
    • @James:是的,问题是每个编译器都根据自己的优先级攻击 C++0x 特性,所以它们都有自己的优势,而且还没有其他人介入。当然使便携性变得困难:)
    猜你喜欢
    • 2012-03-07
    • 1970-01-01
    • 2014-07-04
    • 2019-04-09
    • 2012-09-07
    • 2019-09-24
    • 2012-12-15
    • 2014-05-07
    • 2012-05-28
    相关资源
    最近更新 更多