C++ (and C) source code may be written in any non-ASCII 7-bit character set that includes the ISO 646:1983 invariant character set. However, several C++ operators and punctuators require characters that are outside of the ISO 646 codeset: {, }, [, ], #, \, ^, |, ~. To be able to use character encodings where some or all of these symbols do not exist (such as the German DIN 66003), C++ defines two kinds of alternatives: additional keywords that correspond to the operators that use these characters and special combinations of two or three ISO 646 compatible characters that are interpreted as if they were a single non-ISO 646 character.

The same words are defined in the C programming language in the include file <iso646.h> as macros. Because in C++ these are built into the language, the C++ version of <iso646.h>, as well as <ciso646>, does not define anything.

The following combinations of two and three characters (digraphs and trigraphs) are valid substitutions for their respective primary characters:

Primary

Digraph

Trigraph(until C++17)

{

<%

??<

}

%>

??>

[

<:

??(

]

:>

??)

#

%:

??=

\

??/

^

??'

|

??!

~

??-

Note that trigraphs (but not digraphs) are parsed before comments and string literals are recognized, so a comment such as // Will the next line be executed?????/ will effectively comment out the following line, and the string literal such as "Enter date ??/??/??" is parsed as "Enter date \\??".

(until C++17)

When the parser meets the charater sequence <:: and the subsequent character is neither : nor >, the < is treated as a preprocessor token by itself and not as the first character of the alternative token <:. Thus std::vector<::std::string> won't be wrongly treated as std::vector[:std::string>.