【问题标题】:equal_range and range forequal_range 和范围
【发布时间】:2016-05-02 17:26:41
【问题描述】:

在与我的学生讨论 multimap 时,我注意到一个小改动可能会减少一些样板文件,我想知道是否有人向标准委员会提出了建议,如果有,反应如何。

在相等范围内迭代的规范方法是(取自 cplusplus.com):

// multimap::equal_range
#include <iostream>
#include <map>

int main ()
{
  std::multimap<char,int> mymm;

  mymm.insert(std::pair<char,int>('a',10));
  mymm.insert(std::pair<char,int>('b',20));
  mymm.insert(std::pair<char,int>('b',30));
  mymm.insert(std::pair<char,int>('b',40));
  mymm.insert(std::pair<char,int>('c',50));
  mymm.insert(std::pair<char,int>('c',60));
  mymm.insert(std::pair<char,int>('d',60));

  std::cout << "mymm contains:\n";
  for (char ch='a'; ch<='d'; ch++)
  {
    std::pair <std::multimap<char,int>::iterator,std::multimap<char,int>::iterator> ret;
    ret = mymm.equal_range(ch);
    std::cout << ch << " =>";
    for (std::multimap<char,int>::iterator it=ret.first; it!=ret.second; ++it)
      std::cout << ' ' << it->second;
    std::cout << '\n';
  }

  return 0;
}

在这种情况下,您不能直接使用基于范围的 for 循环,因为 equal_range 的返回类型是 pair&lt;multimap&lt;K,V&gt;::iterator, multimap&lt;K,V&gt;::iterator&gt;。然而,一个简单的包装结构应该允许这样做:

template <typename T>
struct abstract_collection {
  abstract_collection(pair<T, T> its)
  : m_begin(its.first),
    m_end(its.second) {}
  abstract_collection(T begin, T end)
  : m_begin(begin),
    m_end(end) {}

  T begin() const { return m_begin; }
  T end() const { return m_end; }

  T m_begin;
  T m_end;
};

结合向 multimap(和其他)API 添加一个函数,以这种结构返回迭代器,而不是成对返回。

template<typename K, typename V, typename C, typename A>
auto multimap<K, V, C, A>::equal_range_c(K const& k) -> abstract_collection<iterator> {
  return equal_range(k);
}

或者重载采用一对迭代器的std::beginstd::end 版本也应该可以工作:

template <typename T>
T begin(pair<T, T> p) { return p.first; }

template <typename T>
T end(pair<T, T> p) { return p.second; }

这些想法以前是否出现过,如果出现过,委员会的反应是什么?由于某种我没有看到的原因,它们只是不可行或不受欢迎吗?

(请注意,编写代码时并未尝试编译或检查,仅用于说明目的。这可能是错误的。而且它不包含类型检查以仅按应有的方式限制迭代器,因为这增加了复杂性不能用来解释这个想法。)

【问题讨论】:

  • 我相信您正在寻找的是range-v3 library,它很快就会/应该添加到 TS 中。在 C++17 之后的下一个版本中,它应该包含在 C++ 中。
  • 谢谢,这似乎比我建议的任何东西都要强大,这让我很高兴。
  • begin()end() 这样的重载添加到命名空间 std 是未定义的行为。

标签: c++ iterator language-lawyer multimap c++-standard-library


【解决方案1】:

这就是boost::iterator_range 完成的工作,它被range library TS 采用为ranges::iterator_range。该 TS 将在 C++17 之后的某个时间合并。

【讨论】:

    猜你喜欢
    • 2012-04-07
    • 2013-02-27
    • 1970-01-01
    • 2018-06-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-28
    • 1970-01-01
    相关资源
    最近更新 更多