Похоже, вы что-то упустили при определении структуры итератора. Почему итератор имеет указатель на функцию end, которая принимает итератор?
Если вы хотите, чтобы оно было действительно общим, вы могли бы вместо этого использовать это определение:
typedef struct __iterator {
void * ptr_to_container;
int (*end)(void *);
} iterator;
int end(iterator * it) { return it->end(it->ptr_to_container)); }
В определении вектора (и других типов данных) вы можете определить функцию для создания итератора:
static int vector_end(vector * v) { /* implementation omittted */ }
iterator * vector_create_iterator(vector * v)
{
iterator * it = malloc(sizeof(iterator));
it->ptr_to_container = v;
it->end = vector_end;
return it;
}
Однако решение действительно зависит от того, как определены структуры данных. В приведенном выше предложении, каждая структура данных должна предоставить реализацию того, как ее пройти.
В качестве альтернативы вы можете настроить общий интерфейс структуры данных, например
typedef struct _container container;
struct _container {
int (*end)(container * c);
};
Тогда реализация вектора должна «только» заполнить эту структуру контейнера:
typedef struct _vector {
container c;
/* other fields required by the vector */
}
static int vector_end(container * c)
{
vector * v = (vector *) c;
...
}
container * create_vector()
{
vector * v = malloc(sizeof(vector));
v->c.end = vector_end;
return v;
}
... и итератор может работать только с общим контейнером:
typedef struct _iterator {
container * c;
/* other fields used by the iterator, such as current position */
}
int end(iterator * it) { return it->c->end(it->c); }
Из примера кода, о котором идет речь, похоже, что вы смешали эти два подхода: -)