如何减轻在C++中检查迭代器值的语法开销
How can I ease the syntactic overhead of checking iterator values in C++?
基本上,我有点厌倦了写:
std::map<key_t, val_t> the_map;
...
auto iterator = the_map.find(...);
if(iterator != the_map.end()) { // note the "inversed" logic and logically superflous end() call
...
}
真正有意义的是:
if(auto x=the_map.find(...)) {
... // x could either be an iterator or maybe something like boost::optional<val_t>
}
是否有一些现有技术定义了一些帮助程序来缩短!= container.end()
语法,或者我是唯一对此感到恼火的人?
您可以编写一个类模板auto_iterator_impl
,并通过返回auto_iterator_impl
实例的函数模板auto_iterator
使用它,该实例可以隐式转换为true
或false
:
功能和考虑最少的工作实现:
template<typename C>
struct auto_iterator_impl
{
C & c;
typename C::iterator it;
auto_iterator_impl(C & c, typename C::iterator & it) : c(c), it(it) {}
operator bool() const { return it != c.end(); }
typename C::iterator operator->() { return it; }
};
template<typename C>
auto_iterator_impl<C> auto_iterator(C & c, typename C::iterator it)
{
return auto_iterator_impl<C>(c, it);
}
测试代码:
void test(std::map<int, int> & m, int key)
{
if (auto x = auto_iterator(m, m.find(key)))
{
std::cout << "found = " << x->second << std::endl;
x->second *= 100; //change it
}
else
std::cout << "not found" << std::endl;
}
int main()
{
std::map<int,int> m;
m[1] = 10;
m[2] = 20;
test(m, 1);
test(m, 3);
test(m, 2);
std::cout <<"print modified values.." <<std::endl;
std::cout << m[1] << std::endl;
std::cout << m[2] << std::endl;
}
输出:
found = 10
not found
found = 20
print modified values..
1000
2000
在线演示:http://www.ideone.com/MnISh
好吧,如果它对你来说意义重大,那么用一个小包装器:怎么样
template <typename Container>
inline bool find_element(Container const & c,
typename Container::const_iterator & it,
typename Container::value_type const & val)
{
return (it = c.find(val)) == c.end();
}
用法:
std::vector<int> v;
std::vector<int>::const_iterator it;
if (find_element(v, it, 12)) { /* use it */ }
我认为写这样的包装器是最灵活的决定
template<class Iterable>
bool CheckIterator(const typename Iterable::iterator& iter, const Iterable& collection)
{
return !(iter == collection.end());
}
并使用
map<int,string> m;
m[1]="hello";
m[2]="world";
map<int,string>::iterator it = m.find(2);
if(CheckIterator(it,m))
{
cout<<it->second;
}
它可以与其他类型的容器(例如矢量(以及一起使用
这个怎么样?
BOOST_FOREACH(auto &x : c.equal_range(...)) {
// x is a val_t &, or const if c is const.
}
我假设,如果x
是boost::optional<val_t>
是可以的,那么实际上不需要迭代器,只需要值,所以引用是可以的
如果使用boost::iterator_range
而不是std::pair
(这是equal_range
返回的值(,则可以使用基于C++11范围的for循环而不是BOOST_FOREACH。
您可以实现一个包装器函数来为您进行!= map.end()
检查,也可以使用预处理器来使用这样的宏来进行检查:
#define map_find_if(iterator, container, func)
auto (iterator) = (func);
if ((iterator) != (container).end())
这样使用:
map_find_if(iter, map, map.find(key)) {
// found the key
}
// else clause could go here
不过,使用函数可能是一种更干净的实现,而且更多地采用"C++方式"。
如果您愿意将代码集中到一个匿名函数中(看起来您已经在使用auto
了,那么假设是c++11(?
#include <iostream>
#include <map>
template <typename Container, typename ExecF>
void exec_if(Container const& cont, typename Container::const_iterator it, ExecF f)
{
if (it != cont.end())
f();
}
int main(void)
{
std::map<int, int> bar;
bar.insert(std::make_pair(1, 1));
bar.insert(std::make_pair(2, 2));
bar.insert(std::make_pair(3, 3));
auto it = bar.find(2);
exec_if(bar, it, [&it]()
{
std::cout << it->first << ' ' << it->second << std::endl;
});
}
编辑:现在我认为它更干净了
相关文章:
- 1d 智能指针不适用于语法 (*)++
- 助记符和指向成员语法的指针
- 有人能分解一下这个c++模板的语法吗
- C++避免重复声明的语法是什么
- QMetaObject invokeMethod的基于函数指针的语法
- 实现无开销push_back的最佳方法是什么
- 这个语法std::class<>{}(arg1, arg2) 在C++中是什么意思?
- 为什么包含windows.h会产生语法错误,从而阻止类的实例化?(C2146,C2065)
- 单独定义模板化嵌套类方法的正确语法
- 别名模板的专业化 C++11 中没有开销的最佳替代方案
- 共享指针和具有自定义删除程序的唯一指针之间的语法差异背后的任何原因
- 错误 C2760:语法错误:映射迭代器上意外的标记"标识符",预期的";"
- C++标准是否允许<double>在没有开销的情况下实现 std::可选
- 为什么我会收到错误 C2143 语法错误:缺少"*"之前的';'?
- 奇怪的代码抛出编译错误模板< J,int aSize=10> C2143:语法错误:在"<"之前缺少";"
- 使用基类指针调用基类的值构造函数的语法是什么?
- 类型擦除的std::function与虚拟函数调用的开销
- 很好的语法来获取对向量/数组数据的大小引用?
- C++语法运算符功能?
- 如何减轻在C++中检查迭代器值的语法开销