Python允许您编写if e in arr: ...
和 if key in dict: ...
,这很方便。
我们可以使用std::find()
和std::map
与后者做类似的事吗?这样我就可以使用一个通用函数统一处理std::array
和std::map
,而无需明确切换到std::map::find()
。
但如果超载operator==()
是唯一的方法,我宁愿放弃这个想法......
通过“重载operator==()
”我的意思是这样的:
template<typename K>
struct KF {
K&& k;
template <typename V>
friend bool operator==(const typename std::pair<const K, V>& pair, const KF<K>& o) {
return pair.first == o.k;
}
};
template <typename K>
KF<K> keyFinder(K&& k) { return KF<K>{ std::forward<K>(k) }; }
int main() {
std::set<int> s{ 1, 2, };
cout << (std::find(s.begin(), s.end(), 1) == s.end()) << endl; // => 0
cout << (std::find(s.begin(), s.end(), 3) == s.end()) << endl; // => 1
std::map<int, int> m{ {1,10}, {2,20}, };
cout << (std::find(m.begin(), m.end(), keyFinder(1)) == m.end()) << endl; // => 0
cout << (std::find(m.begin(), m.end(), keyFinder(3)) == m.end()) << endl; // => 1
}
当我们以通用方式处理非标量K
时,事情变得更加复杂(完美转发等。?)
答案 0 :(得分:4)
...为什么不编写自己的实用功能?
template <typename TContainer, typename TValue>
bool contains(const TContainer& c, const TValue& x);
您可以使用重载来匹配容器:
template <typename TValue, std::size_t N>
bool contains(const std::array<TValue, N>& c, const TValue& x)
{
return std::find(std::begin(c), std::end(c), x) != std::end(c);
}
template <typename TValue, typename... Ts>
bool contains(const std::map<Ts...>& c, const TValue& x)
{
return c.find(x) != std::end(c);
}
用法:
std::array<int, 2> a{1,2};
std::map<int, int> b{{1,2},{3,4}};
assert(contains(a, 1));
assert(!contains(a, 42));
assert(contains(b, 1));
assert(!contains(b, 42));
如果您希望将来支持其他容器,最好使用 SFINAE 来检查特定表达式是否有效。这种方法效果很好,因为它不关心容器的类型,只关心可以在其上执行哪些操作。
detection idiom可能会很容易通过SFINAE 检查成员的可用性(并且其实现与C ++ 11兼容)。
我还写了一篇关于使用C ++ 17原位检查表达式有效性的文章,这可能是一个有趣的读物。尽管它有标题,但它涵盖了检查表达式有效性的C ++ 11,C ++ 14和C ++ 17技术:
答案 1 :(得分:2)
要回答您的明确问题 - 不,std::find
无法统一为std::map
/ std::unordered_map
和std::array
/ std::vector
工作因为前者是键/值对的集合,后者是值的集合......
您可能希望使用std::find_if
,因为它可以更灵活地定义相等条件,例如像这样(c ++ 1z方法):
#include <array>
#include <map>
#include <string>
#include <algorithm>
#include <type_traits>
template <class T>
struct is_pair: std::false_type { };
template <class K, class V>
struct is_pair<std::pair<K,V>>: std::true_type { };
int main() {
std::map<std::string, int> m {{"abc", 1}, {"cde", 2}, {"efg", 3}};
std::array<int, 5> a{1, 2, 3, 4, 5};
auto lambda = [](auto it) {
if constexpr (is_pair<decltype(it)>::value) {
return it.second == 3;
} else {
return it == 3;
}
};
assert(std::find_if(a.begin(), a.end(), lambda) != a.end());
assert(std::find_if(m.begin(), m.end(), lambda) != m.end());
}
请注意,如果您决定搜索std::vector<std::pair<int, int>>
之类的集合,这种方法将无法按预期工作。