【问题标题】:String type with max length最大长度的字符串类型
【发布时间】:2016-05-03 13:39:44
【问题描述】:

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

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

在所有其他方面,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 可能会更好,但“弄乱”标准库类型似乎有点可怕。

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

【问题讨论】:

  • 当您需要执行string1 + string2 之类的操作时,宽度会发生什么变化?
  • 您的第一直觉是对的(请将std::string value;设为私有)。你观察到基于 std::string 的字符串类的丑陋,暴露了相同的(和扩展的)功能。
  • @user2357112:显然,添加STRING&lt;7&gt; 和STRING&lt;5&gt; 会创建STRING&lt;12&gt;。 “固定”位稍微不那么明显:当且仅当两个输入都固定时,结果才是固定的。
  • @MSalters:看,从您的角度来看这可能很明显,但对于考虑不同用例的人来说,添加 STRING&lt;7&gt; 和 STRING&lt;7&gt; 可能会产生另一个 @ 987654339@ 并添加 STRING&lt;7&gt; 和 STRING&lt;5&gt; 是编译时错误。
  • @user2357112:即使在编程语言中,if 字符串有一个二元运算符+,也有一种强烈的共识,那就是连接。众所周知,Java 只有运算符重载的情况,它的 String+String Python 也使用 +。

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


【解决方案1】:

最简单的方法是修改分配器模板参数。请注意,std::string 是

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

在分配器中,您可以放置​​检查溢出或长度的功能。

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

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

【讨论】:

  • 而短字符串优化意味着可能没有分配。
  • @rici:感谢您的有用评论。我会为我的用例想一个不同的解决方案。
猜你喜欢
  • 2021-09-18
  • 2016-11-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-12
  • 2019-01-19
  • 1970-01-01
  • 2013-08-15
相关资源
最近更新 更多