2016-03-15 114 views
2

我想要有一个std::string like class(比如说,string_n),这样string_n的对象不能超过N个字符。如何限制长度std :: string?

N可以在编译时指定。尝试创建较大长度的string_n可能会断言或抛出异常。

一个选项类似于但是它会错过所有漂亮的成员功能std::string提供。

template <size_t N> 
class string_n { 
    char char_[N + 1]; 
}; 

另一种选择是推出一个新的类,如下所示。

template <size_t N> 
class string_n { 
    public: 
    // constructor and assignment operators with length check 

    ~string_n() = default; 

    // for readers 
    const string& get() const; 

    private: 
    std::string string_; 
}; 

这将需要大量的样板代码。

我有一种感觉,可能会有更好的方法。你会建议什么?

+1

我建议重做'的std :: string'的接口。主要原因是通过使用'std :: string',你将失去没有分配的好处,固定大小的字符串给你。 – SergeyA

+1

@SergeyA:'std :: string :: reserve' ...好吧,这是一个而不是零,但来吧:P –

+0

@阿伦我不知道你的意思是样板代码...如果你想“所有由std :: string提供的好成员函数“,那么你将不得不重新实现它们或者扩展字符串,并重载每个可能增加字符串大小的成员函数,检查它是否超出了你指定的限制。 –

回答

2

此靠拢:

template<size_t N, class CharT, class Traits = std::char_traits<CharT>> 
struct basic_string_n: 
    std::array<CharT, N>, 
    std::experimental::basic_string_view<CharT, Traits> 
{ 
    using storage = std::array<CharT, N>; 
    using access = std::experimental::basic_string_view<CharT, Traits>; 
    using storage::operator[]; 
    using storage::data; 
    using access::size; 

    basic_string_n(basic_string_n const& o): 
    storage(o), 
    access(regen(*this)) 
    {} 
    basic_string_n& operator=(basic_string_n const& o) 
    { 
    *this = (storage const&)o; 
    *this = regen(*this); 
    return *this; 
    } 
    void remove_prefix(std::size_t n) = delete; 
    void remove_suffix(std::size_t n) = delete; 
    void swap(basic_string_n& other) { 
    using std::swap; 
    swap((storage&)*this, (storage&)other); 
    *this = regen(*this); 
    other = regen(other); 
    } 
private: 
    friend access regen(storage& self) { 
    return {self.data(), CharT::length(self.data())}; 
    } 
}; 

在这里,我们有std::experimental::basic_string_view混合字符数组。缺少的是添加或删除字符的操作。