2010-07-15 6 views
3

j'ai une API sous-jacente qui passe un const char * et une longueur:conteneur Poids léger autour const char * et longueur sans copier les données

foo(const char* data, const uint32_t len); 

J'aimerais envelopper ces données/longueur dans un conteneur léger qui peut être itéré et a la capacité d'être accédé au hasard mais pas de faire une copie (par exemple comme un vecteur). Quel est le meilleur moyen d'y parvenir? La donnée const char * n'est pas nécessairement une 'chaîne'; il peut contenir des NULL tout au long. J'utilise STL et Boost. J'ai vu boost :: as_array <> et as_literal <> - est l'un de ces appropriés ici?

Répondre

4

Il serait facile de faire une telle classe. Quelque chose comme ceci:

template <class T> 
class array_ref { 
public: 
    // makes it work with iterator traits.. 
    typedef T   value_type; 
    typedef size_t size_type; 
    typedef ptrdiff_t difference_type; 

    typedef T*  pointer; 
    typedef T*  iterator; 
    typedef T&  reference; 

    typedef const T* const_pointer; 
    typedef const T* const_iterator; 
    typedef const T& const_reference; 

public: 
    array_ref(T *p, size_t n) : data_(p), len_(n) {} 

    // iteration 
    iterator begin()    { return data_; } 
    iterator end()    { return data_ + len_; } 
    const_iterator begin() const { return data_; } 
    const_iterator end() const { return data_ + len_; } 

    // access 
    reference operator[](size_t n)    { return data_[n]; } 
    reference at(size_t n)      { return data_[n]; } 
    const_reference operator[](size_t n) const { return data_[n]; } 
    const_reference at(size_t n) const   { return data_[n]; } 

    // capacity 
    size_t size() const { return len_; } 
    bool empty() const { return size() == 0; } 

    // raw access 
    T* data() const { return data_; } 

    // etc... 
private: 
    T* data_; 
    size_t len_; 
}; 

Cela ressemble à un tas de code, la plupart de ce n'est pas strictement nécessaire. Cependant, puisqu'il s'agit d'un modèle, le compilateur ne générera que du code pour les méthodes utilisées. Et la classe elle-même n'utilise que l'espace pour le pointeur et les membres de longueur.

Mais à la fin, ce n'est vraiment pas un grand avantage. Puisque les pointeurs eux-mêmes sont de bons pointeurs, j'utiliserais probablement juste des pointeurs bruts ici.

+0

Cela ressemble à ce que je cherche. Je pensais que ce genre de chose serait assez commun pour être au moins boost :: cependant. La raison pour laquelle je voudrais faire un itérateur de la data/len est a) de le transporter en C++ (au dessus de l'API C), et b) d'utiliser facilement les templates et classes STL/boost existants . – NuSkooler

0

Je ne pense pas que as_array et/ou as_literal feront ce que vous voulez. Bien que pas très difficile à écrire, je ne connais pas de classe existante destinée à faire ce que vous voulez (ou du moins ce que je pense que vous voulez).

Editer: Je ne devrais probablement pas dire que je ne connais pas ces classes - je ne connais tout simplement pas ceux qui sont particulièrement bien connus, largement utilisés, ou soigneusement testés. Si vous effectuez une recherche dans les archives de comp.lang.C++ et/ou comp.lang.C++, modéré depuis, disons, il y a 12 à 15 ans, vous pouvez probablement en trouver au moins une douzaine en ce moment). À moins que la mémoire ne me manque particulièrement, j'en ai posté un moi-même quelque part le long de la ligne (bien que je ne puisse pas le trouver maintenant ...) Comme vous pouvez le deviner de leur âge, cependant, vous ne voudriez probablement pas utiliser (any?) d'entre eux tels quels - leur utilisation de C++ est souvent assez primitive.

2

Je l'ai utilisé iterator_facade http://www.boost.org/doc/libs/1_43_0/libs/iterator/doc/iterator_facade.html avec iterator_range

vous pouvez facilement utiliser iterator_range pour construire votre emballage, http://www.boost.org/doc/libs/1_42_0/libs/range/doc/utility_class.html#iter_range

boost::iterator_range<char*> range(begin, begin + N); 

cas particuliers peuvent être manipulés avec iterator_facade

+0

Comment iterator_range <> compare-t-il avec le modèle publié par Evan ci-dessus? Sa solution semble être essentiellement ce que je cherche, mais comme je suis déjà en train d'utiliser Boost, s'il y a une «méthode préférée», j'aimerais m'en tenir à cela. – NuSkooler

+0

@Nous il semble assez similaire, essayez de stimuler d'abord, si cela ne fonctionne pas, utilisez le modèle personnalisé – Anycorn

Questions connexes