我很恼火,如果容器包含一个元素{4},则STL容器不会返回contains()
方法true
。所以,我坐下来写下了这个:
false
适用于集合和贴图,但不适用于矢量。或列表。我该怎么办?我应该写一个额外的
template <typename C, typename E>
inline bool contains(const C& container, const E& element) {
return container.find(element) != container.end();
}
以及其他容器的更具体代码?我是否应该继续使用迭代器的次优使用来逐元素地检查?我真的不愿意这样做......或许我没有注意到一些相关的STL功能?
答案 0 :(得分:7)
我认为一个原因是没有std::contains
返回bool
,新手程序员很容易陷入陷阱
if (std::contains(my_container, some_element)) {
auto it = std::find(begin(my_container), end(my_container), some_element);
// process *it
}
现在你正在完成你需要的两倍工作。
编写
只是惯用语auto it = std::find(begin(my_container), end(my_container), some_element);
if (it != end(my_container)) {
// process *it
}
如果你坚持使用contains
功能,那么你可以通过返回std::pair<bool, iterator>
或std::optional<iterator>
来实现两全其美(在图书馆基础知识技术规范中,或者已存在于Boost中,您可以像这样查询:
if (opt = std::contains(my_container, some_element)) {
// process *opt
}
答案 1 :(得分:1)
如果您打算仅在STL容器上使用此函数,并且如果您还不需要处理find
返回的迭代器,那么是的,我建议您为这些容器编写特定代码。这是你能做的最有效的。
template<typename ... Args> struct has_find {};
template<typename T> struct has_find<std::vector<T> > { static const bool value=false; };
template<typename T> struct has_find<std::deque<T> > { static const bool value=false; };
template<typename T, size_t I> struct has_find<std::array<T, I> > { static const bool value=false; };
template<typename T, typename U> struct has_find<std::map<T, U> > { static const bool value=true; };
//... and so on for the handful remaining containers
template<bool has_find>
struct contains_impl
{
template <typename C, typename E>
bool contains(const C& container, E&& element) const
{
return container.find(std::forward<E>(element)) != container.end();
}
};
template<>
struct contains_impl<false>
{
template <typename C, typename E>
bool contains(const C& container, E&& element) const
{
return std::find(container.cbegin(), container.cend(), std::forward<E>(element)) != container.cend();
}
};
template <typename C, typename E>
bool contains(const C& container, E&& element)
{
return contains_impl<has_find<C>::value>().contains(container, std::forward<E>(element));
}
替代方法是使用元编程并让编译器确定该类是否包含特定的find
函数,但这可能有点矫枉过正......
无论如何,如果想要这样,你可以阅读this thread中的食谱。