Можно ли настроить BOOST_FOREACH для типа указателя?

Я пишу C ++ 98 (извините), но работаю с библиотекой C, в которой много объектов хранятся в структурах данных вида:

struct c_container
{
size_t len;
int data[1];
};

struct c_container *make_container(size_t n)
{
if (n == 0)
return NULL;
struct c_container *rv = (struct c_container *)malloc(sizeof(rv->len) + n*sizeof(rv->data));
rv->len = n;
return rv;
}

Я хотел бы сделать итерацию в стиле C ++, используя BOOST_FOREACH, но это не работает. («Старый стиль» ручного вызова функций range_begin и range_end работает).

inline int *range_begin(c_container *c)
{
return c ? &c->data[0] : NULL;
}
inline int *range_end(c_container *c)
{
return c ? &c->data[c->len] : NULL;
}
inline const int *range_begin(const c_container *c)
{
return c ? &c->data[0] : NULL;
}
inline const int *range_end(const c_container *c)
{
return c ? &c->data[c->len] : NULL;
}

namespace boost
{
template<>
struct range_mutable_iterator<c_container *>
{
typedef int *type;
};
template<>
struct range_const_iterator<c_container *>
{
typedef const int *type;
};
}

int main()
{
c_container *coll = make_container(3);
coll->data[0] = 1;
coll->data[1] = 42;
coll->data[2] = -1;

BOOST_FOREACH(int i, coll)
{
std::cout << i << std::endl;
}
}

Это все что должен быть необходимым, согласно http://www.boost.org/doc/libs/1_65_1/doc/html/foreach/extensibility.html (и я проверил это с классами)

Однако в этом примере используется класс, а я использую указатель на класс. Судя по моему исследованию, он использует кодовый путь, который предназначен только для const char * а также const wchar_t *:

In file included from boost-foreach.cpp:6:0:
/usr/include/boost/foreach.hpp: In function ‘bool boost::foreach_detail_::done(const boost::foreach_detail_::auto_any_base&, const boost::foreach_detail_::auto_any_base&, boost::foreach_detail_::type2type<T*, C>*) [with T = c_container, C = mpl_::bool_<false>, const boost::foreach_detail_::auto_any_base& = const boost::foreach_detail_::auto_any_base&]’:
boost-foreach.cpp:65:5:   instantiated from here
/usr/include/boost/foreach.hpp:749:57: error: no match for ‘operator!’ in ‘!* boost::foreach_detail_::auto_any_cast [with T = c_container*, C = mpl_::bool_<false>, typename boost::mpl::if_<C, const T, T>::type = c_container*, const boost::foreach_detail_::auto_any_base& = const boost::foreach_detail_::auto_any_base&](((const boost::foreach_detail_::auto_any_base&)((const boost::foreach_detail_::auto_any_base*)cur)))’
/usr/include/boost/foreach.hpp:749:57: note: candidate is: operator!(bool) <built-in>

Есть ли какая-то дополнительная черта усиления для специализации или что-то еще?

1

Решение

Кажется, трудно определить функции диапазона для указатель типы. Но вы можете определить их для c_container непосредственно. Код выглядит так:

#include <cstdlib>
#include <iostream>
#include <boost/foreach.hpp>

struct c_container
{
size_t len;
int data[1];
};

struct c_container *make_container(size_t n)
{
if (n == 0)
return NULL;
struct c_container *rv = (struct c_container *)malloc(sizeof(rv->len) + n * sizeof(rv->data));
rv->len = n;
return rv;
}

inline int *range_begin(c_container &c)
{
return c.len > 0 ? &c.data[0] : NULL;
}
inline int *range_end(c_container &c)
{
return c.len > 0 ? &c.data[c.len] : NULL;
}
inline const int *range_begin(const c_container &c)
{
return c.len > 0 ? &c.data[0] : NULL;
}
inline const int *range_end(const c_container &c)
{
return c.len > 0 ? &c.data[c.len] : NULL;
}

namespace boost
{
template<>
struct range_mutable_iterator<c_container>
{
typedef int *type;
};
template<>
struct range_const_iterator<c_container>
{
typedef const int *type;
};
}

#define MY_FOREACH(x, y) BOOST_FOREACH(x, *y)

int main()
{
c_container *coll = make_container(3);
coll->data[0] = 1;
coll->data[1] = 42;
coll->data[2] = -1;

//BOOST_FOREACH(int i, *coll)
MY_FOREACH(int i, coll)
{
std::cout << i << std::endl;
}
}

Обратите внимание, что BOOST_FOREACH цикл делает не перебрать указатель типа. В качестве обходного пути вы можете определить свой собственный FOREACH это делается так, как показано в коде выше.

1

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector