Может один станд. рычагов:: basic_string для реализации строки, имеющей ограничение длины?

Помните об этих целях (адаптированный из книги xUnit Тестовые Шаблоны Meszaros)

  • , Тесты должны снизить риск, не представить его.
  • Тесты должно быть легко запустить.
  • Тесты должно быть легко поддержать, поскольку система развивается вокруг них

Некоторые вещи сделать это легче:

  • Тесты должны только перестать работать из-за одной причины.
  • Тесты должны только протестировать одну вещь
  • , Минимизируют тестовые зависимости (никакие зависимости от баз данных, файлов, ui и т.д.)

не забывают, что можно сделать intergration, тестирующий с xUnit платформой также , но сохранить тесты intergration и модульные тесты отдельными

6
задан Steve Guidi 19 October 2009 в 22:56
поделиться

3 ответа

you can pass a custom allocator to std::basic_string which has a max size of whatever you want. This should be sufficient. Perhaps something like this:

template <class T>
class my_allocator {
public:
    typedef T              value_type;

    typedef std::size_t    size_type;
    typedef std::ptrdiff_t difference_type;
    typedef T*             pointer;
    typedef const T*       const_pointer;
    typedef T&             reference;
    typedef const T&       const_reference;

    pointer address(reference r) const             { return &r; }
    const_pointer address(const_reference r) const { return &r; }

    my_allocator() throw() {}

    template <class U>
    my_allocator(const my_allocator<U>&) throw() {}

    ~my_allocator() throw() {}

    pointer allocate(size_type n, void * = 0) {
        // fail if we try to allocate too much
        if((n * sizeof(T))> max_size()) { throw std::bad_alloc(); }
        return static_cast<T *>(::operator new(n * sizeof(T)));
    }

    void deallocate(pointer p, size_type) {
        return ::operator delete(p);
    }

    void construct(pointer p, const T& val) { new(p) T(val); }
    void destroy(pointer p)                 { p->~T(); }

    // max out at about 64k
    size_type max_size() const throw() { return 0xffff; }

    template <class U>
    struct rebind { typedef my_allocator<U> other; };

    template <class U>
    my_allocator& operator=(const my_allocator<U> &rhs) {
        (void)rhs;
        return *this;
    }
};

Then you can probably do this:

typedef std::basic_string<char, std::char_traits<char>, my_allocator<char> > limited_string;

EDIT: I've just done a test to make sure this works as expected. The following code tests it.

int main() {
    limited_string s;
    s = "AAAA";
    s += s;
    s += s;
    s += s;
    s += s;
    s += s;
    s += s;
    s += s; // 512 chars...
    s += s;
    s += s;
    s += s;
    s += s;
    s += s;
    s += s; // 32768 chars...
    s += s; // this will throw std::bad_alloc

    std::cout << s.max_size() << std::endl;
    std::cout << s.size() << std::endl;
}

That last s += s will put it over the top and cause a std::bad_alloc exception, (since my limit is just short of 64k). Unfortunately gcc's std::basic_string::max_size() implementation does not base its result on the allocator you use, so it will still claim to be able to allocate more. (I'm not sure if this is a bug or not...).

But this will definitely allow you impose hard limits on the sizes of strings in a simple way. You could even make the max size a template parameter so you only have to write the code for the allocator once.

5
ответ дан 10 December 2019 в 02:49
поделиться

Я согласен с Эваном Тераном в его решении. Это всего лишь модификация его решения, не более:

template <typename Type, typename std::allocator<Type>::size_type maxSize>
struct myalloc : std::allocator<Type>
{
    // hide std::allocator[ max_size() & allocate(...) ]

    std::allocator<Type>::size_type max_size() const throw()
    {
        return maxSize;
    }
    std::allocator<Type>::pointer allocate
        (std::allocator<Type>::size_type n, void * = 0)
    {
        // fail if we try to allocate too much
        if((n * sizeof(Type))> max_size()) { throw std::bad_alloc(); }
        return static_cast<Type *>(::operator new(n * sizeof(Type)));
    }
};

Имейте в виду, что вы вообще не должны использовать полиморфизм с myalloc . Так что это катастрофа:

// std::allocator doesn't have a virtual destructor
std::allocator<char>* alloc = new myalloc<char>;

Вы просто используете его, как будто это отдельный тип, это безопасно в следующем случае:

myalloc<char, 1024> alloc; // max size == 1024
4
ответ дан 10 December 2019 в 02:49
поделиться

Can't you create a class with std::string as parent and override c_str()? Or define your own c_str16(), c_str32(), etc and implement translation there?

0
ответ дан 10 December 2019 в 02:49
поделиться
Другие вопросы по тегам:

Похожие вопросы: