如何创建没有类型名称的迭代器?
How to create iterator without type names?
例如,我有一个 std::map<int, string> _m;
,我想遍历它。
所以我必须写这样的东西:std::map<int, string>::iterator it = _m.begin()
。
问题是是否可以在不使用类型名称的情况下创建迭代器。编译器在创建迭代器的时候就知道 _m
的类型,那我为什么要自己写这些类型呢?
更新
我忘了说我必须使用旧的 C++ 标准。
您在 auto
关键字之后:
auto it = _m.begin();
Compiler knows the type of _m at the moment of creation of iterator, so why do I need to write those types myself?
是的,这就是导致引入 auto
的 确切 逻辑。
如果你不能使用 C++11,你就会陷入 typedef
之类的困境。引入新标准的全部原因 auto
是因为您面临的确切问题 - 一直手动写出长类型名称很尴尬。
typedef std::map<int, string>::iterator map_itr;
map_itr it = _m.begin();
实际上可以使用模板函数:
template <typename ITERATORTYPE> void myfunc(ITERATORTYPE it) {
//.. do whatever you want with your it
}
然后调用模板:
myfunc(_m.begin());
最好的通用方法是使用 C++11 的 auto
关键字作为类型。在以后的版本中,使用没有任何类型信息的基于范围的循环可以做得更好。
for (it : _m) {
/* ... */
}
如果您坚持使用旧版本,缩短类型名称的唯一方法是创建模板。不过,这可能比写名字更复杂。类似的东西:
template <typename T>
void do_foo(T it, T end) {
for (; it < end; ++it) {
/* ... */
}
}
do_foo(_m.begin(), _m.end());
如果包装算法不是您的算法,您也可以使用 typedef 来缩短它,但您仍然需要输入一次名称。
如果您坚持使用 C++03,如果您 确实 需要它,则无法在不拼写的情况下引用该类型。你能做的最好的事情就是引入一个 typedef
(或更多)这样你只需要输入一次 long 类型:
typedef std::map<int, string> TypeOfM;
typedef TypeOfM::iterator MIterator;
TypeOfM _m;
然而,当您使用标准库算法时,您不必明确命名迭代器:
std::for_each(_m.begin(), _m.end(), /* a functor */);
如果 Boost 是一个选项,而您真的只想迭代,您也可以使用 Boost.Foreach。不幸的是,这仍然需要一个 typedef,因为 map
的 value_type
是一对,因此包含一个 ,
,这会使预处理器出错:
typedef std::pair<const int, string> Pair;
BOOST_FOREACH(const Pair &p, _m)
{
// Do whatever you need
}
由于您正在尝试对其进行迭代,因此您可以尝试 <algorithm>
之一,例如 std::for_each
并传递函数
既然你指定你被及时锁定到 C++98,那么你所拥有的最好的东西就是背后的黑魔法 BOOST_AUTO。
#include <boost/typeof/typeof.hpp>
#include <map>
#include <string>
int main()
{
std::map<int, std::string> m;
BOOST_AUTO(it, m.begin());
}
BOOST_FOREACH 是作为处理循环的类似事物而创建的,无需指定迭代器类型。
#include <boost/foreach.hpp>
#include <iostream>
#include <vector>
int main()
{
std::vector<int> v;
// populate v...
BOOST_FOREACH(int const &i, v)
{
std::cout << i << "\n";
}
}
例如,我有一个 std::map<int, string> _m;
,我想遍历它。
所以我必须写这样的东西:std::map<int, string>::iterator it = _m.begin()
。
问题是是否可以在不使用类型名称的情况下创建迭代器。编译器在创建迭代器的时候就知道 _m
的类型,那我为什么要自己写这些类型呢?
更新 我忘了说我必须使用旧的 C++ 标准。
您在 auto
关键字之后:
auto it = _m.begin();
Compiler knows the type of _m at the moment of creation of iterator, so why do I need to write those types myself?
是的,这就是导致引入 auto
的 确切 逻辑。
如果你不能使用 C++11,你就会陷入 typedef
之类的困境。引入新标准的全部原因 auto
是因为您面临的确切问题 - 一直手动写出长类型名称很尴尬。
typedef std::map<int, string>::iterator map_itr;
map_itr it = _m.begin();
实际上可以使用模板函数:
template <typename ITERATORTYPE> void myfunc(ITERATORTYPE it) {
//.. do whatever you want with your it
}
然后调用模板:
myfunc(_m.begin());
最好的通用方法是使用 C++11 的 auto
关键字作为类型。在以后的版本中,使用没有任何类型信息的基于范围的循环可以做得更好。
for (it : _m) {
/* ... */
}
如果您坚持使用旧版本,缩短类型名称的唯一方法是创建模板。不过,这可能比写名字更复杂。类似的东西:
template <typename T>
void do_foo(T it, T end) {
for (; it < end; ++it) {
/* ... */
}
}
do_foo(_m.begin(), _m.end());
如果包装算法不是您的算法,您也可以使用 typedef 来缩短它,但您仍然需要输入一次名称。
如果您坚持使用 C++03,如果您 确实 需要它,则无法在不拼写的情况下引用该类型。你能做的最好的事情就是引入一个 typedef
(或更多)这样你只需要输入一次 long 类型:
typedef std::map<int, string> TypeOfM;
typedef TypeOfM::iterator MIterator;
TypeOfM _m;
然而,当您使用标准库算法时,您不必明确命名迭代器:
std::for_each(_m.begin(), _m.end(), /* a functor */);
如果 Boost 是一个选项,而您真的只想迭代,您也可以使用 Boost.Foreach。不幸的是,这仍然需要一个 typedef,因为 map
的 value_type
是一对,因此包含一个 ,
,这会使预处理器出错:
typedef std::pair<const int, string> Pair;
BOOST_FOREACH(const Pair &p, _m)
{
// Do whatever you need
}
由于您正在尝试对其进行迭代,因此您可以尝试 <algorithm>
之一,例如 std::for_each
并传递函数
既然你指定你被及时锁定到 C++98,那么你所拥有的最好的东西就是背后的黑魔法 BOOST_AUTO。
#include <boost/typeof/typeof.hpp>
#include <map>
#include <string>
int main()
{
std::map<int, std::string> m;
BOOST_AUTO(it, m.begin());
}
BOOST_FOREACH 是作为处理循环的类似事物而创建的,无需指定迭代器类型。
#include <boost/foreach.hpp>
#include <iostream>
#include <vector>
int main()
{
std::vector<int> v;
// populate v...
BOOST_FOREACH(int const &i, v)
{
std::cout << i << "\n";
}
}