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 to What|.
  • URLs and Paths: A URL like http://example.com/query??/test would 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.