【问题标题】:Readable alternative to std::set::findstd::set::find 的可读替代方案
【发布时间】:2011-07-15 13:49:48
【问题描述】:

通常我不关心集合中物品的价值,我只关心它是否存在。而且反复写if (s.find(val) == s.end()) 又长又丑,可读性差。

有没有一种看起来像if (contains(s,val)) 的好方法,有点标准(stl,boost)。

同样适用于地图的解决方案的奖励积分。

是的,我知道我可以

#define has(X,Y) (X).find(Y) != (X).end()
template<T,U> inline bool has(T s,U elt) {return s.find(elt) != s.end();}

但我宁愿使用最佳实践,也不愿重新发明许多小型实用程序。

【问题讨论】:

  • 复制stackoverflow.com/questions/1701067/…,Adhemar 对为什么 stl 容器不包含 contains() 有一个有趣的看法
  • @Patrick,谢谢,这里的标题有误导性。
  • 为什么丑?任何 C++ 程序员都可以阅读和理解它。仅此一项就成为一种很好的实践,无论某人的个人、宗教信仰如何看待编码风格。为什么你担心一个非 C++ 编程的人是否能理解你的 C++ 代码?
  • @Lundin,C++ 程序员≠ STL 程序员。无论如何,英语 (box.contains(item)) 比 STL 习语更常见。最后也是最重要的一点,它很长并且重复了两次容器的名称,这给了你另一个错误的地方(u.find(x) != v.end())。
  • @Elazar STL 自 1995 年以来一直是 C++ 的一部分?除此之外,我见过的一些最可怕的程序是由试图用自己的宏重新发明一种编程语言的人编写的。这与说“我不喜欢英语单词 programming 几乎是一回事,它是一个很长的词,并不适合描述我所做的事情。以后我将使用换成encoding这个词,因为它显然更适合。如果没有人理解我就不多说了,他们应该学习我自己的正确英语版本。”

标签: c++ boost stl


【解决方案1】:

如果您主要关心的是简洁,那么我建议:

if (s.count(val)) {
  // count == 1 == true, element exists
} else {
  // count == 0 == false, element does not exist
}

但我个人还是更喜欢检查 find 与 end 因为意图更明确。值得我多打几下。

【讨论】:

  • 为了便于阅读,我仍然会使用0==s.count(val),以减少下一位读者的意外因素(嗯?count 返回 bool?)。另外它不适用于地图。但是很好,很有创意! +1
  • 是的,但是如果您要写出s.count(val) == 0,您不妨多敲五下键并使用查找/结束。此外,它适用于地图——有一个std::map::count 方法。
  • 我知道,这就是为什么这对我来说不是最好的方式。当然,std::map::count 存在,抱歉。
【解决方案2】:

if (s.find(val) == s.end()) 是检查容器中是否存在项目的“标准”方式。据我所知,Boost 或标准库都没有提供任何类型的函数来返回一个布尔值,表示容器中是否存在元素。

如果你想这样做,你必须自己实现它。标准库或 Boost 提供看起来不同的现有功能是没有意义的。

如果您想这样做,模板化实现将是最佳解决方案。在 C++ 中使用定义通常不是一个好主意。

【讨论】:

  • @dauphic,我不想这么说,但事实上“标准库或 Boost 提供看起来不同的现有功能是没有意义的。”真的是假的。为什么vector.find 不是std::find 的特化? BOOST_FOREACH 呢?实际上,可读性的重点是以简洁易读的方式实现现有功能。编写代码供您阅读,而不是让计算机执行...
  • std::vector 没有find 功能。 BOOST_FOREACH 的目的是减少繁琐的样板代码,不一定是为了使其更易于阅读,尽管它是作为副作用的;如果您不使用 typedef,通常可以使用长度超过 120 个字符的迭代器类型。将返回的迭代器与end 进行比较并不难理解,它是检查容器中是否存在元素的标准方法。任何 C++ 开发人员都应该不假思索地知道这段代码在做什么。
  • 变量名也会变长。只需解释一下为什么 BOOST_FOREACH 被认为是样板缩减器,而 contains(x,y) 不是。两者都做同样的事情,输入更少,让你的代码看起来更像英语。抱歉,vector 确实没有 find,但是 map 有,并且可以通过 find 的专门化来实现。 empty()size()==0 呢?它只是更具可读性。 map::operator[]呢,就相当于(*((this-&gt;insert(make_pair(x,T()))).first)).second。我相信我能找到更多类似的例子。
  • @dauphic,哦,使用 STL 迭代对象的标准方法是 for (auto it(o.begin());it!=o.end();++it),使用 STL 的每个人都应该熟悉它,但是,为了简洁/可读性,我们需要 BOOST_FOREACH。
  • @Elazar:那是 C++0x,更好的方法是 range-for(内置 BOOST_FOREACH)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-07-28
  • 1970-01-01
  • 2010-11-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多