2010-06-02 91 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,但是我個人認爲只需創建一個自定義結構來保存這些信息就更具可讀性。