在容器中查找内容并立即检查返回迭代器的有效性的最短形式是:
if (const auto it = find_in(container, something))
{
do something with it
}
要编译此文件
it
必须可转换为
bool
(不用说
它
必须从底层搜索操作返回的常规迭代器类型派生)。下面的代码包含
find_in()
实用程序
std::vector
和
std::map
。为其他容器添加重载很简单。
#include <algorithm>
#include <vector>
#include <map>
#include <iostream>
template<class It>
class OptionalIterator : public It
{
It end_;
public:
OptionalIterator(It it, It end) : It(it), end_(end) {}
explicit operator bool() const
{
return static_cast<const It&>(*this) != end_;
}
};
////////////////////// find_in() a range ///////////////////////////////////
template<class It, class X>
OptionalIterator<It>
find_in(It start, It end, const X& x)
{
return OptionalIterator<It>(std::find(start, end, x), end);
}
////////////////////// find_in() a std::vector /////////////////////////////
template<class T, class A, class X>
OptionalIterator<typename std::vector<T, A>::const_iterator>
find_in(const std::vector<T, A>& v, const X& x)
{
return find_in(v.begin(), v.end(), x);
}
template<class T, class A, class X>
OptionalIterator<typename std::vector<T, A>::iterator>
find_in(std::vector<T, A>& v, const X& x)
{
return find_in(v.begin(), v.end(), x);
}
////////////////////// find_in() a std::map ////////////////////////////////
template<class K, class V, class C, class A, class X>
OptionalIterator<typename std::map<K, V, C, A>::const_iterator>
find_in(const std::map<K, V, C, A>& m, const X& x)
{
typedef typename std::map<K, V, C, A>::const_iterator It;
return OptionalIterator<It>(m.find(x), m.end());
}
template<class K, class V, class C, class A, class X>
OptionalIterator<typename std::map<K, V, C, A>::iterator>
find_in(std::map<K, V, C, A>& m, const X& x)
{
typedef typename std::map<K, V, C, A>::iterator It;
return OptionalIterator<It>(m.find(x), m.end());
}
////////////////////////////////////////////////////////////////////////////
int main()
{
std::vector<int> v{2, 4, 1, 3};
if ( const auto it = find_in(v, 4) )
std::cout << "4 in v is at index " << it - v.begin() << std::endl;
std::map<int, int> m{{1, 23}, {4, 56}};
if ( const auto it = find_in(m, 4) )
std::cout << "m[4]=" << it->second << std::endl;
return 0;
}