如何使用 std::iota 和 std::pair?

How to use std::iota with std::pair?

假设我必须使用这个我无法修改的模板:

// cannot modify
template <typename C,typename T> 
void foo(C& c,const T& t) {
    // ...
    std::iota(std::begin(c),std::end(c),t);
    // ...
}

It fails when c is a container of std::pairs:

#include <vector>
#include <utility>
#include <numeric>
int main()
{
    std::vector<std::pair<int,int>> y(5);
    foo(y,std::pair<int,int>{1,2});
}

y 的预期内容是 {1,2},{2,3},{3,4},{4,5},{5,6}

错误是:

In file included from /opt/compiler-explorer/gcc-9.2.0/include/c++/9.2.0/numeric:62,
                 from <source>:2:
/opt/compiler-explorer/gcc-9.2.0/include/c++/9.2.0/bits/stl_numeric.h: In instantiation of 'void std::iota(_ForwardIterator, _ForwardIterator, _Tp) [with _ForwardIterator = __gnu_cxx::__normal_iterator<std::pair<int, int>*, std::vector<std::pair<int, int> > >; _Tp = std::pair<int, int>]':
<source>:9:14:   required from 'void foo(C&, const T&) [with C = std::vector<std::pair<int, int> >; T = std::pair<int, int>]'
<source>:16:34:   required from here
/opt/compiler-explorer/gcc-9.2.0/include/c++/9.2.0/bits/stl_numeric.h:94:4: error: no match for 'operator++' (operand type is 'std::pair<int, int>')
   94 |    ++__value;
      |    ^~~~~~~~~
Compiler returned: 1

好的,我知道 std::pair 没有 operator++,但如果我自己提供一个,我不能将其范围限制为 foo

当不允许定义 template <typename T,typename U> std::pair<T,U>::operator++ 时,如何将 std::iotastd::pair<T,U> 的容器一起使用?

请注意,std::iota() 具有不同的迭代器类型和 increment/assign 的值:

template< class ForwardIt, class T >
void iota( ForwardIt first, ForwardIt last, T value );

这可用于使用不同于(尽管可分配给)向量元素类型的值类型。

在我的例子中,我只是从 std::pair 中派生了一个类型(将在 std::vector 中使用)并将增量运算符添加到该派生类型:

#include <numeric>
#include <iostream>
#include <vector>

template <typename T1, typename T2>
struct PairIncT: std::pair<T1, T2> {
    PairIncT(T1 first, T2 second): std::pair<T1, T2>(first, second) { }
    PairIncT& operator++() { ++this->first; ++this->second; return *this; }
};

int main()
{
  // a vector of pairs
  using VectorIU = std::vector<std::pair<int, unsigned>>;
  VectorIU v(5);
  // make corresponding inc. type for vector element
  using PairIU = PairIncT<
    VectorIU::value_type::first_type,
    VectorIU::value_type::second_type
  >;
  // fill vector
  std::iota(v.begin(), v.end(), PairIU( 1, 2 ));
  // show vector
  for (const VectorIU::value_type &elem : v) {
    std::cout << "{ " << elem.first << ", " << elem.second << " }\n";
  }
}

输出:

{ 1, 2 }
{ 2, 3 }
{ 3, 4 }
{ 4, 5 }
{ 5, 6 }

Live Demo on coliru