Namespaces
Variants

Alternative operator representations

From cppreference.net
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements (loops)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications ( until C++17* )
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Specifiers
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Class-specific function properties
Special member functions
Templates
Miscellaneous

C++(及C)源代码可以使用任何包含 ISO 646:1983 不变字符集的非ASCII 7位字符集编写。然而,部分C++运算符和标点符号需要ISO 646代码集之外的字符: {, }, [, ], #, \, ^, |, ~ 。为了能在某些或全部这些符号不存在的字符编码(例如德国 DIN 66003 标准)中使用,C++定义了以下由ISO 646兼容字符组成的替代表示。

目录

替代标记

对于使用非ISO646字符的若干运算符和其他标记存在替代拼写。在语言的所有方面,每个替代标记的行为与其主标记完全相同,除了拼写不同( 字符串化运算符 可使拼写可见)。双字母替代标记有时被称为"二合字母"。尽管由四个字符组成, % : % : 也被视为二合字母。

主运算符 替代表示
&& and
&= and_eq
& bitand
| bitor
~ compl
! not
!= not_eq
|| or
|= or_eq
^ xor
^= xor_eq
{ <%
} %>
[ <:
] :>
# %:
## %:%:

三字符组 (于 C++17 中移除)

以下三字符组(三连符)在 识别注释和字符串字面量之前被解析 ,每个三连符的出现都会被替换为对应的主字符:

主要符号 三字符序列
{ ??<
} ??>
[ ??(
] ??)
# ??=
\ ??/
^ ??'
| ??!
~ ??-

由于三字符组在早期阶段就被处理,因此像 // Will the next line be executed?????/ 这样的注释会有效注释掉下一行代码,而像 "Enter date ??/??/??" 这样的字符串字面量会被解析为 "Enter date \\ ??"

注释

字符 & ! 在 ISO-646 标准下保持不变,但为使用这些字符的标记提供了替代形式,以适应更为严格的历史字符集。

相等运算符 == 没有替代拼写(例如 eq ),因为字符 = 在所有支持的字符集中都存在。

与C的兼容性

相同的词汇在C编程语言中通过头文件 <iso646.h> 以宏的形式定义。由于在C++中这些是语言内置特性,C++版本的 <iso646.h> 以及 <ciso646> 并未定义任何内容。而非单词的二合字母(例如 < % )则是核心语言的一部分,无需包含任何头文件即可使用(否则在缺少 # 字符的字符集上将无法使用)。

关键词

and and_eq bitand bitor compl not not_eq or or_eq xor xor_eq

示例

以下示例演示了若干替代记号的使用。

%:include <iostream>
struct X
<%
    compl X() <%%> // 析构函数
    X() <%%>
    X(const X bitand) = delete; // 复制构造函数
    // X(X and) = delete; // 移动构造函数
    bool operator not_eq(const X bitand other)
    <%
       return this not_eq bitand other;
    %>
%>;
int main(int argc, char* argv<::>) 
<%
    // 带引用捕获的 lambda 表达式:
    auto greet = <:bitand:>(const char* name)
    <%
        std::cout << "Hello " << name
                  << " from " << argv<:0:> << '\n';
    %>;
    if (argc > 1 and argv<:1:> not_eq nullptr)
        greet(argv<:1:>);
    else
        greet("Anon");
%>

可能的输出:

Hello Anon from ./a.out

参考文献

  • C++23 标准 (ISO/IEC 14882:2024):
  • 5.5 替代记号 [lex.digraph]
  • C++20 标准 (ISO/IEC 14882:2020):
  • 5.5 替代记号 [lex.digraph]
  • C++17 标准 (ISO/IEC 14882:2017):
  • 5.5 替代记号 [lex.digraph]
  • C++14 标准 (ISO/IEC 14882:2014):
  • 2.4 三字符序列 [lex.trigraph]
  • 2.6 替代标记 [lex.digraph]
  • C++11 标准 (ISO/IEC 14882:2011):
  • 2.4 三字符序列 [lex.trigraph]
  • 2.6 替代记号 [lex.digraph]
  • C++03 标准 (ISO/IEC 14882:2003):
  • 2.3 三字符序列 [lex.trigraph]
  • 2.5 替代记号 [lex.digraph]
  • C++98 标准 (ISO/IEC 14882:1998):
  • 2.3 三字符序列 [lex.trigraph]
  • 2.5 替代标记 [lex.digraph]

参见

C 文档 关于 替代运算符和记号