【问题标题】:Subclass std::string for additional type safety?子类 std::string 以获得额外的类型安全?
【发布时间】:2018-07-20 21:47:45
【问题描述】:

我想知道是否可以将 std::string 子类化以创建具有相同行为但含义不同的新类型,例如 UTF-8 字符串。我正在考虑类似 Django 的 safestring 或 Nim 的 distinct 子类型。

我希望这种类型能够表达“这个字符串是通过我的一个 UTF-8 生成函数创建的,并且保证是有效的 UTF-8(而不是其他一些编码)”。那么类型系统可以防止我意外混合编码。

UTF-8 只是一个例子,它可以是任何其他“不同的字符串”——例如“用户输入”、“自然语言”,而不是机器可读的键,等等。我不想强制执行,例如UTF-8 有效性,只是我的字符串的来源和“风味”(类型/种类/变体)。我只想能够编写以下内容,如果aString 不是MyString,则让它失败:

void processString(MyString str);
// ...
processString(aString);

我已经阅读了关于subclassing std::string 的其他讨论,但不确定对于这个非常具体的案例会得出什么结论。我的类不会有额外的字段,所以切片不会有问题,也不需要重写方法,所以std::string 的方法都不是虚拟的应该没问题。我必须在我的子类中定义什么才能让它按我想要的方式工作吗?

【问题讨论】:

  • 回答您提出的仅有的两个问题:是的,有可能;并且您将必须定义修改字符串的所有方法。此外,缺少任何其他字段并不能消除对象切片问题,因为您的类,除非它从std::string 私下继承,否则仍然可以简单地切片成std::string。所以你必须私下继承std::string。然后,除了实现所有修改包含字符串的方法外,还公开继承所有const字符串方法。你在这里问的真正问题是:是的,这是很多工作。
  • 你打算如何实现operator[]的UTF-8字符串?
  • @AndriyTylychko:就像普通的std::string,按字节计算。我不会追求不同的行为,我只想将一些对象标记为“保证 UTF-8”。提供能够识别字素集群等的功能超出了范围,将是一个完全不同的项目。
  • @SamVarshavchik:如果我公开继承但没有附加字段且没有虚函数,那么切片问题如何?内存布局不应该一样吗?
  • 相同的内存布局完全没有任何意义。对象切片与内存布局无关。没有什么可以阻止将您的子类的实例分配给string &,即使您的对象在其方法中强制执行 UTF-8 正确性,现在您有一个string &,您可以将任何非 UTF-8 内容转储到它,直接。

标签: c++ std


【解决方案1】:

标准库容器不是为继承而设计的。它们被设计为简单而快速。一些字符串方法对于例如不是很有用。 UTF-8 字符串。例如。 size()operator[] 可能会产生令人惊讶的结果。将概念分开是有意义的。这可以通过聚合轻松实现。

class UTF8_string
{
public:
    // UTF-8 specific functionality

    std::string const& byte_string() const;
private:
    std::string content;
};

在这种情况下,当用户调用utf8_string.byte_string().size() 时,其意图很明显。

【讨论】:

  • 为什么你有一个非常量 byte_string() 引用返回?这允许外部代码将内部std::string 修改为他们想要的不是 UTF-8 的任何内容。让byte_string() 按值或常量引用返回会更有意义
  • @RemyLebeau:是的,const 版本就足够了。谢谢,已编辑
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-06-24
  • 2015-09-24
  • 1970-01-01
  • 1970-01-01
  • 2021-02-05
  • 2020-12-04
  • 1970-01-01
相关资源
最近更新 更多