2010-06-02 99 views
2

我混合了一些C和C++库,并且只有一个指针可用于在回调函数中执行一些工作。我需要做的就是遍历一个向量。下面是一个简化的,未测试的示例:使用不带容器的迭代器


bool call_back(void* data){ 
    done=... 
    if (!done) cout << *data++ << endl; 
    return done; 
} 

注意,该功能是在C中的extern "C"块++。将调用call_back直到返回true。我希望它在每次调用它时都会关注下一个元素。 data是一个指向我可以从代码中的其他地方传入的指针(上例中的迭代器,但可以是任何东西)。从data可能会用来计算done。我看到两个明显的选项,给data

  1. data点到我的矢量。
  2. data指向我的向量的迭代器。

我不能使用迭代器没有.end()方法可用,对吧?我不能单独使用矢量(除非我可能会开始删除它的数据)。我可以用矢量和迭代器构造一个结构,但有没有更好的方法?你会怎么做?

+0

这个函数只能从C++代码中调用吗? – 2010-06-02 04:44:45

+0

是的,我期望它在C++代码文件中始终是一个外部“C”。 – User1 2010-06-02 12:52:04

回答

3

为什么不将数据指向具有所需信息的结构?

关于旧的“C”风格回调的一点是void *可以指向任何对象。你的回调函数知道类型是什么,但它可以是任何东西。

typedef struct Plop 
{ 
    std::vector<int>::iterator begin; 
    std::vector<int>::iterator end; 
} Plop; 

bool call_back(void* data) 
{ 
    // Or static_cast<> for the pedantic. 
    // I like reinterpret_cast<> because it is a clue to humans that this is dangerious 
    // and as long as the object was originally a Plop* pointer it is guaranteed to work. 
    Plop* info = reinterpret_cast<Plop*>(data); 

    bool done= info.begin == info.end; 

    if (!done) cout << *data++ << endl; 
    return done; 
} 
+0

我真的很想为这个函数避免一个新的结构。有关铸造的有趣评论。 – User1 2010-06-02 12:57:54

0

如何解引用迭代器并将其值传递给call_back?然后在函数返回后增加它?

1

我不能使用迭代器没有.end()方法可用,对不对?

不可以。您可以使用带有调用.end()函数结果的迭代器。你不需要继续调用.end()函数......所以如果你只存储了两个迭代器,那么你就是黄金。

我不能单独使用一个矢量(除非我可能会开始删除它的数据)。

不是一个人,但有一个std :: size_t索引,那么这就是你所需要的。

我可以用矢量和迭代器做一个结构,但有没有更好的方法?你会怎么做?

如果你不担心支持其他容器类型,然后我会用:

template<typename T> struct CALLBACK_DATA 
{ 
     std::vector<T>* array; 
     std::size_t index; 
}; 

如果你可能需要支持多种容器类型,然后我会用:

template<typename T> struct CALLBACK_DATA 
{ 
    typedef std::vector<T> container_type; 
    typedef typename std::vector<T>::const_iterator const_iterator; 
    const_iterator current; 
    const_iterator end; 
}; 

所以,是的,我要么通过矢量和索引或一对迭代器,我会构造一个结构来保存数据。如果你想避免创建一个结构,那么你可以使用std::pair,但是我个人认为只需创建一个自定义结构来保存这些信息就更具可读性。