Легкий контейнер вокруг константного символа * и длины без копирования данных - PullRequest
3 голосов
/ 15 июля 2010

У меня есть базовый API, который передает const char * и длину:

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

Я хотел бы обернуть эти данные / длину в легкий контейнер, который может быть повторен и имеет возможностьбыть случайным образом доступным , но не делать копию (например, как вектор).Каков наилучший способ достичь этого?Данные const char * не обязательно являются «строкой»;он может содержать NULL.

Я использую STL и Boost.Я видел boost :: as_array <> и as_literal <> - один из них уместен здесь?

Ответы [ 3 ]

4 голосов
/ 15 июля 2010

Было бы легко сделать такой класс. Примерно так:

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_;
};

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

Но, в конце концов, это не так уж и много. Поскольку сами указатели являются хорошими указателями, я, вероятно, просто использовал бы здесь необработанные указатели.

2 голосов
/ 15 июля 2010

Я использовал iterator_facade http://www.boost.org/doc/libs/1_43_0/libs/iterator/doc/iterator_facade.html вместе с iterator_range

вы можете легко использовать iterator_range для создания вашей оболочки, 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);

особые случаи могут быть обработаны с помощью iterator_facade

0 голосов
/ 15 июля 2010

Я не думаю, что as_array и / или as_literal будут делать то, что вы хотите.Хотя написать не так уж сложно, я не знаю ни одного существующего класса, предназначенного для того, чтобы делать то, что вы хотите (или, по крайней мере, то, что я думаю, что вы хотите).

Редактировать: я, вероятно, не должен говорить, что я неЯ не знаю каких-либо таких классов - я просто не знаю ни одного, который особенно хорошо известен, широко используется или тщательно проверен.Если вы будете искать в архивах comp.lang.c ++ и / или comp.lang.c ++., Модерируемых, скажем, 12–15 лет назад или около того, вы, вероятно, найдете не менее дюжины (по крайней мере, при условии, что поиск в группе новостей Google работаетв данный момент).Пока память не подведет меня особенно сильно, я отправил один сам где-то вдоль линии (хотя я не могу найти это прямо сейчас ...) Как вы можете догадаться с их возраста, вы, вероятно, не захотите использовать большинство(любой?) из них как есть - их использование C ++ часто довольно примитивно.

...