Макрос для цикла итератора для итераций STL
концепция
так, я пытаюсь определить макрос, чтобы упростить следующий код:
for (vector<TYPE>::iterator iter = iterable.begin();
iter != iterable.end(); iter++)
и
for (map<TYPE, TYPE>::iterator iter = iterable.begin();
iter != iterable.end(); iter++)
etc.
Существующие Работы
пока у меня есть
#define every(iter, iterable) ::iterator iter = iterable.begin(); iter != iterable.end(); iter++
for (vector<TYPE> every(iter, iterable))
но я хотел бы упростить это еще больше.
цель
в идеале, я хотел бы иметь возможность сделать
for (every(iter, iterable))
что означает, что мне нужно как-то получить class<TYPE>
объекта iterable. Заключаться в следующем возможно? Если да, то как я могу это сделать?
условия
- это, в идеале, должно войти в (относительно) большую кодовую базу, уже настроенную для доступа к
6 ответов
ответ тут не зависит от C++11, но ему нужно typeof
, что некоторые компиляторы могут не иметь. Должен работать с любым недавним g++
#define For(iter, iterable) for(typeof((iterable).begin()) iter = (iterable).begin(); iter != (iterable).end(); ++iter)
можно использовать for(auto iter = iterable.being(); iter != iterable.end(); iter++)
Если ваш компилятор поддерживает C++0x.
Если вы используете C++11, вы можете использовать новый синтаксис.
vector<double> v(9, 0.5);
auto total = 0.;
for (auto x: v) {
total += x;
}
Если вам нужна ссылка для изменения значений, вы можете использовать:
vector<double> v(9, 0.5);
for (auto &x: v) {
x = 5;
}
просто скомпилируйте с флагом-std=c++0x.
Если вы используете c++11, используйте auto!
for (auto it = vec.begin(); it != vec.end(); it++)
{
}
edit:
Это будет макрос:
#define every(iter, iterable) auto iter = iterable.begin(); iter != iterable.end(); iter++
затем реализовать:
for(every(iter, iterable))
{
UseElement(*iter);
}
почему бы просто не использовать std::for_each ? В C++11 вы можете использовать их с lambdas.
C++11 также имеет базовый цикл диапазона.
template<typename T>
void Foo(const T& x)
{
for (auto& i : x)
std::cout << i << std::endl;
}
конечно, обязательна...МАКРОСЫ-ЗЛО
Если вы застряли с древним компилятором вы всегда можете сделать
typedef std::map<int,int> IntMap_t;
IntMap_t tmap;
for( IntMap_t::iterator iter = tmap.begin();
iter != tmap.end();
++iter)
{
}
Я хотел бы расширить довольно хороший ответ Аарона Макдейда. Я нашел очень похожее решение в pre-C++0x окружающая среда (я назвал макро как FOREACH
). Это работает для нормального iterator
и reverse iterator
. Но как это сделать на const_iterator
и const_reverse_iterator
? К сожалению cbegin()
является функцией C++0x, и typeof(container)::const_iterator
не работает. Очень маленький класс template может решить эту проблему. Вот мой код:
template <class T>
struct IterType { typedef typename T::const_iterator citer_t; };
#define FOREACHCONST(_CIter, _Container) \
for(IterType<typeof(_Container)>::citer_t _CIter = (_Container).begin(); \
_CIter != (_Container).end(); ++_CIter )
он работает точно так же, как FOREACH
.
интересно, что это не работает внутри шаблонной функции. В этом случае typename
ключевое слово должно быть добавлено прямо перед IterType
, но в этом случае он не может использоваться вне шаблонной функции.