C++ 为什么对std::regex_traits没有定义<;char32_t>;(因此没有提供std::basic_regex<;char32_t>;)?

C++ 为什么对std::regex_traits没有定义<;char32_t>;(因此没有提供std::basic_regex<;char32_t>;)?,c++,regex,c++11,C++,Regex,C++11,我想在UTF-32代码点上使用正则表达式,并发现这表明std::regex_traits必须由用户定义,因此std::basic_regex完全可以使用。似乎没有计划在未来对此进行任何更改 为什么会这样呢 这是否与Unicode表示组合码点必须被视为等同于单个码点表示的事实有关(如umlaut“ä”表示为单个码点,或者a和点表示为两个独立的点) 考虑到只支持单个代码点字符的简化,这一特性可以很容易地定义吗?或者这不是微不足道的,还是需要进一步的限制 regex匹配的某些方面是区域设置感知的,结果

我想在UTF-32代码点上使用正则表达式,并发现这表明std::regex_traits必须由用户定义,因此std::basic_regex完全可以使用。似乎没有计划在未来对此进行任何更改

  • 为什么会这样呢

  • 这是否与Unicode表示组合码点必须被视为等同于单个码点表示的事实有关(如umlaut“ä”表示为单个码点,或者a和点表示为两个独立的点)

  • 考虑到只支持单个代码点字符的简化,这一特性可以很容易地定义吗?或者这不是微不足道的,还是需要进一步的限制

  • regex匹配的某些方面是区域设置感知的,结果是
    std::regex\u traits
    对象包含或引用
    std::locale
    对象的实例。C++标准库只为“代码> char < /COD>和 WCARYTT 字符提供了区域,因此没有代码标准,用于<代码> CHAR32×T(除非它与“代码> WCARYTT >相同”,并且这个限制被传递到正则表达式中。

  • 你的描述不准确。Unicode定义了两个字符串之间的规范等价关系,该关系基于使用NFC或NFD对两个字符串进行规范化,然后逐码点比较规范化值。它没有简单地将规范等价定义为代码点和代码点序列之间的等价,因为规范化不能简单地逐个字符地完成。规范化可能需要将组合字符重新排序为规范顺序(在规范(取消)组合之后)。因此,它不容易适应于通常是单个字符的区域转换的C++模型。

    C++标准库不实现任何Unicode规范化算法;在C++中,与许多其他语言一样,两个字符串<代码> L“\U00 E4”(胡)和“代码> L”\U066\U0308“<代码>(A))将作为不同的比较,尽管它们是规范等价的,并且对人类读取器来说就像同一个字形。(在我写这个答案的机器上,这两个图形的呈现方式有细微的不同;如果仔细观察,你会发现第二个图形中的umlaut稍微偏离了其视觉最佳位置。这违反了Unicode的要求,即规范等效字符串具有完全相同的呈现方式。)

    如果要检查两个字符串的规范等效性,则需要使用Unicode规范化库。不幸的是,C++标准库不包括任何这样的API;您可以查看(其中还包括)

    无论如何,正则表达式匹配(在C++标准中指定的程度)不规范目标字符串。这是允许的,它建议将目标字符串显式规范化为某种规范化形式,并编写模式以使用规范化为该形式的字符串:

    对于大多数功能齐全的正则表达式引擎,在规范等价下很难进行匹配,这可能涉及字符的重新排序、拆分或合并……实际上,regex API并没有设置为匹配部分字符或处理不连续的选择。还有许多其他的边缘情况……然而,构建与NFD(或NFKD)文本匹配的模式是可行的。这可以通过以下方式实现:

    • 将要匹配的文本放入定义的规范化表单(NFD或NFKD)
    • 让用户设计正则表达式模式以与定义的规范化表单相匹配。例如,模式不应包含在该规范化形式中不会出现的字符,也不应包含不会出现的序列
    • 像往常一样,在逐个代码点的基础上应用匹配算法
  • 创建
    std::regex_traits
    char32_t
    专门化的大部分工作将是创建
    char32_t
    locale对象。我从来没有试过做这两件事;我怀疑这需要相当多的注意细节,因为有很多奇怪的角落案例


  • C++标准对正则表达式匹配的细节有点含糊,将详细信息留给外部文档来说明正则表达式的每一种味道(并且没有一个完整的解释,说明如何将这些外部规范应用到字符类型之外的每一种类型上)。然而,匹配是逐字符进行的这一事实是可以推断的。例如,在§28.3要求[re.req]中,表136包括负责逐字符等效算法的语言环境方法:

    表达式:
    v.translate(c)
    返回类型:
    X::char\u类型
    断言:返回一个字符,使得对于被视为等同于
    c
    的任何字符
    d
    ,则
    v.translate(c)==v.translate(d)

    类似地,在对默认“修改的ECMAScript”风格的正则表达式匹配的描述(§28.13)中,标准描述了正则表达式引擎如何匹配两个字符(一个在模式中,一个在目标中):(第14.1段):

    在正则表达式有限状态机与字符序列匹配期间,使用以下规则比较两个字符
    c
    d

  • 如果
    (flags()®ex\u constants::icase)
    如果
    traits\u inst.translate\u nocase(c)=traits\u inst.translate\u nocase(d)
    ,这两个字符是相等的

  • o