【问题标题】:C++ less verbose alternative to passing container.start() and container.end()传递 container.start() 和 container.end() 的 C++ 不那么冗长的替代方案
【发布时间】:2011-06-18 19:43:26
【问题描述】:

我声明一个vector<Bla> blaVec 并编写一个函数:

template<typename Iterator>
void doSomething(Iterator first, Iterator last) { ... }

然后我在blaVec 上调用这个函数:

doSomething(blaVec.begin(), blaVec.end());

但是,我真的想要像 doSomething(blaVec) 这样更短的东西,但不必在函数定义中指定 vector。基本上,有没有一个好的标准方法来指定第一个迭代器或者可能是一系列 [begin,end] 迭代器,就像 Boost.Range 所做的那样。

我是一个算法专家,所以我真的不想涉及过于通用的复杂解决方案。我一生中的大部分时间都在编写这样的函数:

void doSomething(vector<int> & bla) { ... }

然而,这些天来,我经常写 doSomething 来操作 listdequevector 所以需要一个更通用的解决方案,这就是我使用迭代器的原因。但这似乎是一个过于冗长的解决方案。你有什么建议?

  1. doSomething(vector & bla) { ... }
  2. doSomething(Iterator first, Iterator last) { ... }
  3. doSomething(/* 一些范围数据结构 */) { ... }

【问题讨论】:

  • 你提到了 Boost.Range,所以......为什么不使用它呢?它也有各种漂亮的功能,比如延迟评估等等。
  • 我不确定它有多常用。我喜欢使用很多程序员都在使用的技术,因为我的重点是算法而不是软件设计方面。我不喜欢站在软件工程的前沿。有时会导致时间下降。
  • 额外的冗长很少,但迭代器范围接口的灵活性要好得多。此外,如果您只需要遍历整个范围,std::for_each 正是为此而设计的。

标签: c++ boost stl iterator range


【解决方案1】:

如果你觉得那很冗长,那么你可以用这个来包装它:

template<typename Container>
void doSomething(Container &c) 
{
  doSomething(c.begin(), c.end()); //internally call the iterator version.
}

并使用这个函数,而不是迭代器版本。

此外,当您不希望函数对容器中的所有元素进行操作时,您可以使用迭代器版本。例如,

doSomething(c.begin(), c.begin() + 5); //operate on first 5 elements
                                       //assuming c.begin()+5 makes sense

【讨论】:

  • +1。请参阅 boost::range 了解这方面的终极工具。使用 boost::begin/boost::end 允许 Container 为任何类型,包括 c 数组和字符串。
  • @Macke: std::stringbeginend 成员函数。
  • @Xeo:我指的是 c-strings (const char*)。抱歉不清楚。
  • c++0x 未标记。否则,我们可以使用 doSomething( begin(c), end(c));它甚至适用于 c 字符串。
【解决方案2】:

更喜欢第二个,因为它更灵活。

我不觉得它很冗长,但如果你真的坚持,你可能想为它定义一个宏,例如:

#define FULLITER(a) a.begin(), a.end()

(只要确保a 是一个简单的表达式,所以它不会被执行两次。)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-12-26
    • 2017-02-23
    • 2015-10-31
    • 2017-06-22
    • 2014-01-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多