如何使用std::rotate来旋转第一个成员为const的pair数组?

How can I use std::rotate to rotate an array of pairs whose first member is const?

本文关键字:const pair 数组 成员 第一个 std 何使用 rotate 旋转      更新时间:2023-10-16

我正在实现一个映射,并且我想在一对数组上使用std::rotate,其中第一个成员是const(因此在插入映射时不能更改键)。它相当于下面不能编译的代码:

#include <utility>
#include <array>
#include <algorithm>
int main()
{
    typedef std::pair<const int, int> map_entry;
    std::array<map_entry, 3> a{ { {2, 0}, {1, 0}, {3, 0} } };
    std::rotate(&a[0], &a[1], &a[3]);
}

不幸的是,我无法控制pair的类型("value_type"),它需要定义如下:与std::unordered_map:

兼容
    template <class K, class T, class H, class P, class A>
    class unordered_map
    {
    public:
        typedef K key_type;
        typedef std::pair<const K, T> value_type;
        typedef T mapped_type;

是否有办法让我使用std::旋转这样一个数组,也许通过删除const的某种方式?

下面是编译错误:

$ g++ -std=c++11 xx.cxx
In file included from /usr/lib/gcc/i686-pc-cygwin/4.8.2/include/c++/utility:70:0,
                 from xx.cxx:1:
/usr/lib/gcc/i686-pc-cygwin/4.8.2/include/c++/bits/stl_pair.h: In instantiation of ‘std::pair<_T1, _T2>& std::pair<_T1, _T2>::operator=(std::pair<_T1 , _T2>&&) [with _T1 = const int; _T2 = int]’:
/usr/lib/gcc/i686-pc-cygwin/4.8.2/include/c++/bits/stl_algo.h:1610:22:   required from ‘void std::__rotate(_RandomAccessIterator, _RandomAccessIterat or, _RandomAccessIterator, std::random_access_iterator_tag) [with _RandomAccessIterator = std::pair<const int, int>*]’
/usr/lib/gcc/i686-pc-cygwin/4.8.2/include/c++/bits/stl_algo.h:1686:59:   required from ‘void std::rotate(_FIter, _FIter, _FIter) [with _FIter = std:: pair<const int, int>*]’
xx.cxx:9:36:   required from here
/usr/lib/gcc/i686-pc-cygwin/4.8.2/include/c++/bits/stl_pair.h:170:8: error: assignment of read-only member ‘std::pair<const int, int>::first’
  first = std::forward<first_type>(__p.first);
        ^
In file included from /usr/lib/gcc/i686-pc-cygwin/4.8.2/include/c++/bits/stl_pair.h:59:0,
                 from /usr/lib/gcc/i686-pc-cygwin/4.8.2/include/c++/utility:70,
                 from xx.cxx:1:
/usr/lib/gcc/i686-pc-cygwin/4.8.2/include/c++/bits/move.h: In instantiation of ‘void std::swap(_Tp&, _Tp&) [with _Tp = const int]’:
/usr/lib/gcc/i686-pc-cygwin/4.8.2/include/c++/bits/stl_pair.h:199:23:   required from ‘void std::pair<_T1, _T2>::swap(std::pair<_T1, _T2>&) [with _T1  = const int; _T2 = int]’
/usr/lib/gcc/i686-pc-cygwin/4.8.2/include/c++/bits/stl_pair.h:256:7:   required from ‘void std::swap(std::pair<_T1, _T2>&, std::pair<_T1, _T2>&) [wit h _T1 = const int; _T2 = int]’
/usr/lib/gcc/i686-pc-cygwin/4.8.2/include/c++/bits/stl_algobase.h:147:22:   required from ‘void std::iter_swap(_ForwardIterator1, _ForwardIterator2)  [with _ForwardIterator1 = std::pair<const int, int>*; _ForwardIterator2 = std::pair<const int, int>*]’
/usr/lib/gcc/i686-pc-cygwin/4.8.2/include/c++/bits/stl_algo.h:1616:28:   required from ‘void std::__rotate(_RandomAccessIterator, _RandomAccessIterat or, _RandomAccessIterator, std::random_access_iterator_tag) [with _RandomAccessIterator = std::pair<const int, int>*]’
/usr/lib/gcc/i686-pc-cygwin/4.8.2/include/c++/bits/stl_algo.h:1686:59:   required from ‘void std::rotate(_FIter, _FIter, _FIter) [with _FIter = std:: pair<const int, int>*]’
xx.cxx:9:36:   required from here
/usr/lib/gcc/i686-pc-cygwin/4.8.2/include/c++/bits/move.h:176:11: error: assignment of read-only reference ‘__a’
       __a = _GLIBCXX_MOVE(__b);
           ^
/usr/lib/gcc/i686-pc-cygwin/4.8.2/include/c++/bits/move.h:177:11: error: assignment of read-only reference ‘__b’
       __b = _GLIBCXX_MOVE(__tmp);
           ^

简单:不要使用std::pair。设计一个具有所需语义的类并使用它。特别是,不要使数据成员为const。相反,将它们设为私有并编写访问器来强制const-ness。int first() const;, int second() const;int& second();是一个很好的开始。但它们真的应该被命名为key()value(),或者其他更符合你的设计的名字。

我找到了解决办法。在内部,我存储了没有const (mutable_value_type)的值对,但是我仍然用const定义了value_type,这就是当你解引用迭代器时返回的值。

template <class K, class T, class H, class P, class A>
class unordered_map
{
public:
    typedef K key_type;
    typedef std::pair<const K, T> value_type;
    typedef std::pair<K, T>       mutable_value_type;