1. Introduction
This paper proposes making 
2. Changes since R2
- 
     Added a reference to [P2930] and how it differs from the current proposal. 
3. Changes since R1
- 
     Added a debug format to avoid ambiguity when formatting error codes in maps. 
- 
     Added SG16 poll results. 
4. Changes since R0
- 
     Changed the title from "Formatting of std::error_code" to "Fix encoding issues and add a formatter for std::error_code" to reflect the fact that the paper also fixes [LWG4156]. 
- 
     Specified that error_category :: name () 
- 
     Made transcoding in error_category :: message () 
5. Polls
SG16 poll results for R0:
Poll 1: Forward P3395R0 to LEWG amended to specify an encoding for 
SF F N A SA 1 6 0 0 0
Outcome: Strong consensus.
6. Motivation
std :: error_code ec ; auto size = std :: filesystem :: file_size ( "nonexistent" , ec ); std :: cout << ec ; 
This works and prints 
However, the following code doesn’t compile:
std :: ( "{} \n " , ec ); 
Unfortunately, the existing inserter has several issues, such as I/O manipulators applying only to the category name rather than the entire error code, resulting in confusing output:
std :: cout << std :: left << std :: setw ( 12 ) << ec ; 
This prints:
generic :2
Additionally, it doesn’t allow formatting the error message and introduces potential encoding issues, as the encoding of the category name is unspecified.
7. Proposal
This paper proposes adding a 
The default format will produce the same output as the 
std :: ( "{} \n " , ec ); 
Output:
generic:2
It will correctly handle width and alignment:
std :: ( "[{:>12}] \n " , ec ); 
Output:
[ generic:2]
Additionally, it will allow formatting the error message:
std :: ( "{:s} \n " , ec ); 
Output:
No such file or directory
(The actual message depends on the platform.)
The main challenge lies in the standard’s lack of specification for the
encodings of strings returned by 
virtual const char * name () const noexcept = 0 ; 
Returns: A string naming the error category.
virtual string message ( int ev ) const = 0 ; 
Returns: A string that describes the error condition denoted by 
In practice, implementations typically define category names as string literals, meaning they are in the ordinary literal encoding.
However, there is significant divergence in message encodings. libc++ and
libstdc++ use 
The following table summarizes the differences:
| libstdc++ | libc++ | Microsoft STL | |
| POSIX |  |  | N/A | 
| Windows | / ACP |  | ordinary literals / ACP | 
Obviously none of this is usable in a portable way through the generic 
To address this, the proposal suggests using the C locale encoding (execution
character set), which is already employed in most cases and aligns with
underlying system APIs. Microsoft STL’s implementation has a number of bugs in 
An alternative approach could involve communicating the encoding from 
8. Previous work
A formatter for 
9. Wording
Add to "Header <system_error> synopsis" [system.error.syn]:
// [system.error.fmt], formatter template < class charT > struct formatter < error_code , charT > ; 
Add a new section "Formatting" [system.error.fmt] under "Class 
template < class charT > struct formatter < error_code , charT > { constexpr void set_debug_format (); constexpr typename basic_format_parse_context < charT >:: iterator parse ( basic_format_parse_context < charT >& ctx ); template < class FormatContext > typename FormatContext :: iterator format ( const error_code & ec , FormatContext & ctx ) const ; }; 
constexpr void set_debug_format (); 
Effects: Modifies the state of the 
constexpr typename basic_format_parse_context < charT >:: iterator parse ( basic_format_parse_context < charT >& ctx ); 
Effects: Parses the format specifier as a error-code-format-spec and stores the
parsed specifiers in 
error-code-format-spec:
   fill-and-alignopt widthopt 
where the productions fill-and-align and width are described in [format.string]. If the 
Returns: An iterator past the end of the error-code-format-spec.
template < class FormatContext > typename FormatContext :: iterator format ( const error_code & ec , FormatContext & ctx ) const ; 
Effects: If the 
- 
     If the ordinary literal encoding is UTF-8, then let msg ec . message () 
- 
     Otherwise, let msg ec . message () 
Otherwise, let 
Writes 
Returns: An iterator past the end of the output range.
Modify [syserr.errcat.virtuals]:
virtual const char * name () const noexcept = 0 ; 
Returns: A string in the ordinary literal encoding naming the error category.
...
virtual string message ( int ev ) const = 0 ; 
    Returns: A string 
    of multibyte characters in the executon character
set
     that describes the error condition denoted by 
10. Implementation
The proposed