【发布时间】: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 内容转储到它,直接。