2016-03-15 112 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混合字符數組。缺少的是添加或刪除字符的操作。