C+中的Unicode标识符和源代码+;11? 我发现新的C++标准 2.11 Identifiers [lex.name] identifier: identifier-nondigit identifier identifier-nondigit identifier digit identifier-nondigit: nondigit universal-character-name other implementation-defined character

C+中的Unicode标识符和源代码+;11? 我发现新的C++标准 2.11 Identifiers [lex.name] identifier: identifier-nondigit identifier identifier-nondigit identifier digit identifier-nondigit: nondigit universal-character-name other implementation-defined character,unicode,syntax,c++11,Unicode,Syntax,C++11,附加文本 标识符是任意长的字母和数字序列。标识符中的每个通用字符名应指定一个字符,该字符在ISO 10646中的编码属于指定的范围之一 在E.1中。[……] 我不太明白这是什么意思。例如,从旧std开始,我习惯于写一个“通用字符名”\u89ab。但是在标识符中使用这些。。。?真的吗 新标准对Unicode更开放吗?我没有提到新的文字类型“uHello\u89ab thing”u32,我想我理解这些。但是: (可移植的)源代码是否可以采用任何unicode编码,如UTF-8、UTF-16或任何(

附加文本

标识符是任意长的字母和数字序列。标识符中的每个通用字符名应指定一个字符,该字符在ISO 10646中的编码属于指定的范围之一 在E.1中。[……]

我不太明白这是什么意思。例如,从旧std开始,我习惯于写一个“通用字符名”
\u89ab
。但是在标识符中使用这些。。。?真的吗

新标准对Unicode更开放吗?我没有提到新的文字类型
“uHello\u89ab thing”u32
,我想我理解这些。但是:

  • (可移植的)源代码是否可以采用任何unicode编码,如UTF-8、UTF-16或任何(如何定义的)代码页
  • 我是否可以在其中写入带有
    \u1234
    的标识符
    myfu\u1234ntion
    (无论出于何种目的)
  • 或者我可以使用unicode在ICU中定义的“字符名”吗

    const auto x = "German Braunb\U{LOWERCASE LETTER A WITH DIARESIS}r."u32;
    
    const auto x = "German Braunb\U{LOWERCASE LETTER A WITH DIARESIS}r."u32;
    
    或者甚至在源本身的标识符中?那将是一种享受。。。咳嗽

我认为所有这些问题的答案都是否定的,但我无法将其与标准中的措辞可靠地对应起来……:-)

编辑:我找到了“翻译的2.2阶段[lex.Phases]”,第1阶段:

如有必要,将以实现定义的方式将物理源文件字符映射到基本源字符集[…]。接受的物理源文件字符集由实现定义。[…]任何源文件字符不在基本格式中 源字符集(2.3)替换为指定该字符的通用字符名。(一个实现可以使用任何内部编码,只要源文件中遇到的实际扩展字符和源文件中表示为通用字符名的相同扩展字符(即使用\uxxx表示法)被等效处理,除非此替换以原始字符串文字还原。)

通过阅读本文,我现在认为,编译器可以选择接受UTF-8、UTF-16或它希望的任何代码页(通过元信息或用户配置)。在第1阶段,它将其转换为ASCII格式(“基本源字符集”),在该格式中,Unicode字符被其
\unnn
符号替换(或者编译器可以选择继续使用其Unicode表示,但必须确保以相同的方式处理另一个
\unnn


您认为如何?

我认为其目的是允许在标识符中使用Unicode字符,例如:

long pöjk;
ostream* å;
本文认为
int\u0401;
是兼容的代码,尽管它基于C99而不是C++0x

新标准是否对Unicode更加开放

关于在标识符中允许通用字符名,答案是否定的;早在C99和C++98中就允许在标识符中使用UCN。但是编译器直到最近才实现这一特定要求。我认为Clang 3.3引入了对这一点的支持,GCC对此已经有一段时间的实验性功能。Herb Sutter也在他2013年的Build演讲“C++的未来”中提到,该功能在某个时候也会出现在VC++中(尽管IIRC Herb将其称为C++11功能;实际上它是C++98功能)

不期望使用UCS写入标识符。相反,期望的行为是使用源编码写入所需的字符。例如,源代码如下所示:

long pörk;
不是:

但是,UCS也有另一个用途;并非所有编译器都需要接受相同的源代码,但现代编译器都支持某些编码方案,其中至少基本源字符具有相同的编码(即,现代编译器都支持某些ASCII兼容编码)

UCS允许您仅使用基本字符编写源代码,但仍使用扩展字符命名。例如,在编写源代码中的字符串文字“°”时,这非常有用,将编译为CP1252和UTF-8:

char const *degree_sign = "\u00b0";
此字符串文字在多个编译器上编码为适当的执行编码,即使源代码不同,只要编译器至少对基本字符共享相同的编码

(可移植的)源代码是否可以采用任何unicode编码,如UTF-8、UTF-16或任何(如何定义的)代码页

该标准不要求它,但大多数编译器将接受UTF-8源代码。Clang仅支持UTF-8源代码(尽管它对字符和字符串文本中的非UTF-8数据具有一定的兼容性),gcc允许指定源代码编码,并包括对UTF-8的支持,VC++将猜测编码,并可使其猜测UTF-8

(更新:VS2015现在提供了一种强制源和执行字符集为UTF-8的方法。)

我是否可以在标识符中写入\u1234 myfu\u1234ntion(用于任何目的)

是的,规范规定了这一点,尽管正如我所说,并非所有编译器都实现了这一要求

或者我可以使用unicode在ICU中定义的“字符名”吗

const auto x = "German Braunb\U{LOWERCASE LETTER A WITH DIARESIS}r."u32;
const auto x = "German Braunb\U{LOWERCASE LETTER A WITH DIARESIS}r."u32;
不,不能使用Unicode长名称

或者甚至在来源本身的标识符中?那将是一种治疗…咳嗽

<>如果编译器支持一个包含你所需扩展字符的源代码编码,那么在源代码中书写的字符必须与等效的UCN完全相同。所以,如果使用支持C++规范要求的编译器,那么可以在其源字符集中直接写入任何字符。在源代码中输入,而不必费心编写UCS。

目前的gcc版本(到目前为止版本为5.2)仅支持ASCII,在某些情况下还支持EBCDIC输入文件。因此,unicode字符
> cat /tmp/test.cpp
#include <iostream>

int main()
{
    int α = 10;
    std::cout << "α = " << α << std::endl;
    return 0;
}
> clang++ /tmp/test.cpp -o /tmp/test
> /tmp/test 
α = 10