一个杠杆能标准:: basic_string的实现具有长度限制的字符串?
题
我正在与一个低级别的API,它接受一个char*
和数字值来表示一个字符串,它的长度,分别工作。我的代码使用std::basic_string
并调用这些方法与合适的翻译。不幸的是,许多这些方法接受不同大小的字符串长度(即最多(unsigned char
),MAX(short
),等...),我被卡住编写代码,以确保我的字符串情况下不超过规定的最大长度由低级API。
缺省情况下,std::basic_string
实例的最大长度由size_t
的最大值(或者最大值(unsigned int
)或最大(__int64
))的约束。有没有一种方法来操纵特性和std::basic_string
实施的分配器实现,这样我可以在指定地点size_t
我自己要使用的类型?通过这样做,我希望能充分利用std::basic_string
执行中的任何现有的边界检查,所以我没有这样做,执行转换时。
我的初步调查表明,这是不可能没有写我自己的串类,但我希望我忽略了一些:)
解决方案
您可以通过自定义分配器来std::basic_string
拥有任何你想要的最大尺寸。这应该是足够了。也许是这样的:
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;
}
};
然后你也许可以做到这一点:
typedef std::basic_string<char, std::char_traits<char>, my_allocator<char> > limited_string;
编辑:我只是做了一个测试,以确保该工程按预期。下面的代码测试它。
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;
}
这是最后s += s
会把它在上面,并导致std::bad_alloc
例外,(因为我的极限是只是短期的64K)。不幸的是gcc的std::basic_string::max_size()
实现不立足于使用分配器的结果,所以它仍然声称能够分配更多。 (我不知道这是否是一个错误或不...)。
但是,这绝对可以让你强加给字符串的大小硬限制在一个简单的方法。你甚至可以使最大尺寸模板参数,所以你只需要编写代码的分配一次。
其他提示
我埃文特兰同意关于他的溶液。这仅仅是他的解决方案的一个变形例没有更多:
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
无法创建性病一类::字符串作为家长和覆盖c_str()? 可以定义自己的c_str16(),c_str32()等,并实现翻译呢?