Why C++ Removed Trigraph Sequences
Trigraph sequences were introduced to solve hardware limitations of the 1980s by allowing programmers to type essential C and C++ characters using limited keyboards. Over time, these three-character sequences became obsolete, confusing, and prone to introducing silent bugs into modern source code. Consequently, the C++ Standards Committee deprecated trigraphs in C++14 and officially removed them from the standard in C++17.
What Trigraph Sequences Were
Trigraphs were three-character sequences that began with two question
marks (??) followed by a distinct third character. The
preprocessor replaced these sequences with a corresponding single
character during the earliest phase of translation. For example:
??=became#??(became[??)became]??<became{??>became}??/became\??!became|??'became^??-became~
This mechanism allowed developers on systems with restricted 7-bit character sets, such as ISO 646 national variants, to write standard C and C++ code.
The Problem of Early Translation
The primary technical issue with trigraphs was that the compiler evaluated them in Phase 1 of translation—before tokenization, comment stripping, or string parsing.
Because substitution happened indiscriminately across the entire file, trigraphs frequently altered code unintentionally:
- String Literals: A string containing
What??!was automatically converted toWhat|. - URLs and Paths: A URL like
http://example.com/query??/testwould turn??/into a backslash (\), creating an unexpected escape sequence or line continuation. - Escaped Newlines: The sequence
??/followed immediately by a newline would be replaced with\, which joined the current line with the next, silently commenting out functional code if it occurred inside a comment.
These behaviors led to insidious bugs that were difficult to track down because the source code visually appeared correct.
Technological Obsolescence
When trigraphs were standardized in C90 and inherited by C++98,
keyboards missing basic punctuation like {, },
[, and ] were still in active use on legacy
mainframes and international terminals. By the 2010s, modern character
encodings (such as UTF-8) and standardized keyboard layouts had become
ubiquitous. The original hardware restrictions that necessitated
trigraphs no longer existed in modern development environments.
The Presence of Safer Alternatives
C++ provides alternative tokens—often called digraphs (such as
<:, :>, <%, and
%>) as well as named operators like and,
or, and not. Unlike trigraphs, digraphs are
handled during lexical analysis (tokenization) rather than character
translation. This means digraphs do not trigger inside string literals
or comments, eliminating the risk of accidental replacement.
The Path to Removal
The proposal to remove trigraphs (N4087) noted that the feature
caused far more harm than good to the broader C++ ecosystem. Despite
minor resistance from developers working with legacy IBM EBCDIC
mainframes, the ISO committee concluded that toolchains targeting
specific legacy environments could provide trigraph support via
non-standard compiler flags (such as GCC's
-ftrigraphs).
Standard C++ officially eliminated the requirement for compilers to replace trigraphs in C++17, reducing compiler complexity and preventing unexpected source-text transformations.