【问题标题】:force key type of a std::map not to be const强制 std::map 的键类型不是 const
【发布时间】:2011-07-21 09:09:38
【问题描述】:

C++ 参考告诉我们一个 std::map

typedef pair<const Key, T> value_type;

是否可以强制 Key Type 不是 const ? 我需要在

之类的模板方法中执行此操作
template<class T> // T represent a map in general (std::map, boost::unordered_map or whatever..)
void foo(const T& m)
{
  typename T::value_type::first_type x;
  x=0; // Wrong because x is const ...
}

【问题讨论】:

    标签: c++ stl map


    【解决方案1】:

    不,不是。

    这是因为 map 基于 key 执行其内部排序。如果你可以自己修改密钥,不管你是否愿意,一切都会崩溃。

    您应该使用提供的 API 函数;如果使用 one 会导致 Key 值发生更改(实际上我认为不会这样做),则可能会发生适当的内部重新排序。

    想想 getter 和 setter,以及它们在提供替代混乱/危险的直接成员访问方面的用途。


    但是,你可以这样写:

    template<class T>
    void foo(const T& m)
    {
       typename T::key_type x;
       x = 0;
    }
    

    std::map 类型别名

    key_type                Key
    mapped_type             T
    value_type              pair<const Key,T>
    key_compare             Compare
    value_compare           Nested class to compare elements
    allocator_type          Allocator
    reference               Allocator::reference
    const_reference         Allocator::const_reference
    iterator                Bidirectional iterator
    const_iterator          Constant bidirectional iterator
    size_type               Unsigned integral type (usually same as size_t)
    difference_type         Signed integral type (usually same as ptrdiff_t)
    pointer                 Allocator::pointer
    const_pointer           Allocator::const_pointer
    reverse_iterator        reverse_iterator<iterator>
    const_reverse_iterator  reverse_iterator<const_iterator>
    

    【讨论】:

    • 有关信息,Boost.MultiIndex 提供了update 方法,该方法允许更改给定对象(就地),然后在所有索引中正确地重新定位它。显然,这比 STL map/unordered_map 先进得多 :)
    【解决方案2】:

    typename T::key_type 将在不添加 const 限定符的情况下为您提供密钥类型。

    【讨论】:

      【解决方案3】:

      对于您的简单问题,以前的答案应该足够了。作为一种更通用的方法,您可以使用 boost::remove_const(来自 boost type_traits)将 const 限定符删除到一个类型。

      template<class T> // T represent a map in general (std::map, boost::unordered_map or whatever..)
      void foo(const T& m)
      {
        typedef typename T::value_type::first_type X; //is const
        typedef typename boost::remove_const<X>::type NonConstX;
        NonConstX x;
        x=0; 
      }
      

      【讨论】:

        【解决方案4】:

        键类型必须是 const。如果您确定不会更改地图的顺序,则可以抛弃迭代器的 const-ness。如果你弄错了,这可能会导致丑陋的错误。

        【讨论】:

        • 抱歉,丹尼斯,如果您使用 map 按对象成员对实例化对象进行排序,这样做是非常有效的。如果您不更改该成员,那么您还没有更改订单。完全不可变的容器不是一个非常有用的工具。
        • 不。地图存储pair&lt;const key, value&gt; 对象。请注意,密钥存储在 const 对象中。修改 const 对象,无论为什么在其他地方使用它,都是未定义的行为。如果成员是可变的,并且它不会影响排序,那么您可能会没事,但这种情况非常罕见。
        • 如果确定排序的键部分没有改变,它可以正常工作。您仍然可以更改不更改顺序的键对象实例的其他成员。
        • 这是未定义的行为。它可能看起来有效,但这并不安全。
        猜你喜欢
        • 2011-04-02
        • 2020-12-21
        • 1970-01-01
        • 2021-04-21
        • 2023-03-20
        • 1970-01-01
        • 1970-01-01
        • 2015-11-02
        • 1970-01-01
        相关资源
        最近更新 更多