具有最大长度的字符串类型

时间:2016-01-26 20:22:03

标签: c++ string c++11 stdstring

我需要实现类似于std:string的C ++ 11或C ++ 14类型STRING,但具有以下附加约束/功能:

  1. 声明期间指定的WIDTH参数。 STRING会 如果长度大于WIDTH
  2. 则抛出异常
  3. 声明期间指定的可选FIXED参数。如果STRING的长度不等于WIDTH
  4. ,则会抛出异常

    在所有其他方面,STRING应该表现得像std::string,并且展示与std:string相同的成员函数(例如.append()等。)。

    我的第一直觉是使用一个包含STRING的模板类std::string,如下所示:

    template<int WIDTH= 0, bool FIXED = false>
    class STRING {
        static_assert(WIDTH >= 0, "WIDTH of STRING cannot be negative.");
    public:
        STRING() : value{} { }
    
        STRING(const std::string &s) { if (is_valid(s)) value = s; }
    
        STRING(const char c[]) { if (is_valid(c)) value = c; }
    
        STRING& operator=(const std::string& s){ if (is_valid(s)) value = s;}
        operator std::string() const { return value; }
    
    
        std::string value;
    
    private:
        bool is_valid(const std::string &s) {
            if (WIDTH && s.length() > WIDTH)
                throw std::length_error{"STRING assignment failed. STRING too long."};
            if (FIXED && s.length() != WIDTH)
                throw std::length_error{"STRING assignment failed. STRING has wrong length."};
            return true;
        }
    };
    

    但是,上面的STRING模板类没有公开std::string个成员函数,我不想重新实现整个std::basic_char函数集,所以我认为我的方法基本上是错误。我怀疑某种程度上扩展std::string可能会更好,但是对标准库类型的“混乱”似乎有点可怕。

    我不确定这里最好的方法是什么,并且正确方向的指示将非常受欢迎。

1 个答案:

答案 0 :(得分:5)

实现此目的的最简单方法是修改allocator模板参数。请注意,std::string

的简写
std::basic_string<char, std::char_traits<char>, std::allocator<char>>

在分配器内部,您可以设置功能以检查溢出或长度。

关于如何编写自定义分配器的建议,请查看this Q&AHoward Hinnant's website有一个关于如何限制需要复制的样板的示例。

正如@rici所说,大多数实现都将使用短字符串优化(SSO)。这意味着字符串类将具有union基于堆栈的小存储(通常为24个字节左右)和三个指向堆的指针。这意味着对于小字符串,可能会完全忽略提供的分配器。这实际上意味着您无法将字符串限制为非常小(低于SSO阈值)。