Deprecate implicit conversion
from bool
to character types
- Document number:
- P3765R0
- Date:
2025-07-12 - Audience:
- EWG
- Project:
- ISO/IEC 14882 Programming Languages — C++, ISO/IEC JTC1/SC22/WG21
- Reply-to:
- Jan Schultke <janschultke@gmail.com>
- Co-authors:
- Hana Dusíková <hanicka@hanicka.net>
- GitHub Issue:
- wg21.link/P3765/github
- Source:
- github.com/Eisenwave/cpp-proposals/blob/master/src/deprecate-bool-conv.cow
to character types
serve little purpose in the language, and invite bugs.
We propose to deprecate them.
Contents
Introduction
Proposal
Explicit casts should be allowed
Impact on existing code
Implementation experience
Wording
References
1. Introduction
is equivalent to
,
and the
overload is called with
.
Surprisingly, every compiler accepts this code at the time of writing,
with no warning and no errors.
That is because
→
conversion
is neither a narrowing conversion, nor does it change the sign of the operand,
so it does not trigger any checks.
Semantically (assuming ASCII-compatible encoding),
in
→
conversion,
is converted to U+0000
is converted to U+0001
Seeing that these implicit conversions also invite bugs like the one above, that makes them not just useless, but actively harmful to the language, qualifying them for removal. Similarly, [P1120R0] deprecated array-to-pointer conversion in equality comparison of two arrays, a bug-prone and virtually useless conversion.
2. Proposal
The goal of this proposal is to deprecate implicit conversion
from
to character types.
That is, to
,
,
,
, and
.
Conversions to
and
are not affected.
That is because these types are used for numerics and not to represent characters,
so e.g.
→
represents a conversion from
to
and from
to
,
which is sometimes used in branchless programming:
is incremented if
is odd.
Note that branchless programming is generally not affected by a
→
deprecation.
For example, in the expression
,
both operands are converted to
due to the usual arithmetic conversions
and integral promotion.
→
conversion actually takes place when calling
a function with
parameter with a
argument,
when storing a
value in a
variable, and
other such "direct" scenarios.
2.1. Explicit casts should be allowed
While an implicit
→
conversion is likely a bug,
we want users to have a way to suppress deprecation warnings
and to retain the old behavior, in the unlikely event they wanted the conversion to happen.
There are various other conversion, like
→
or
→
which follow this pattern of
"explicit conversions only".
In summary, the intended semantics are as follows:
While most of these are obvious, some decisions require rationale:
-
should be deprecated because direct-initialization, unlike casts, does not generally opt into all possible conversions. For example,d2
is valid, whilestatic_cast < int * > ( void_ptr )
, for someint * p ( void_ptr )
.void * void_ptr -
should be deprecated because list-initialization is generally more restrictive. For instance, it does not permit narrowing conversions, andd5
is ill-formed whileI { void_ptr }
is okay, whereI ( void_ptr )
isI
.int * -
andk1
should be okay because they are defined in terms ofk2
.static_cast
3. Impact on existing code
During discussion of this proposal with various members of the C++ community, no one was able to produce an example of where this conversion is used in existing code. However, we did not yet perform an extensive survey of large code bases.
Furthermore, there are GCC targets that do not comply with the C99 standard,
where
is defined to be
(not
).
The following snippet includes GCC definitions for Solaris 2 ([GccSolaris2]):
/* ??? This definition of int8_t follows the system header but does not conform to C99. Likewise int_fast8_t, int_least8_t. */ #define INT8_TYPE "char"
Since
→
conversion could plausibly happen
in branchless programming,
hypothetically,
some code on such non-compliant platforms is affected.
In any case,
deprecation warnings are easily resolved by performing an explicit conversion,
or by prepending
to the
operand,
which would trigger integral promotion
and result in
→
conversion instead.
4. Implementation experience
A [ClangWarning] has been implemented in a fork, which triggers in the deprecated cases.
5. Wording
The wording changes are relative to [N5008].
Change [conv.integral] paragraph 1 as follows:
A prvalue of an integer type
can be converted to a prvalue of another integer type
.
The conversion is deprecated ([depr.conv.bool.char]) if
-
isS
andbool
is a character type ([basic.fundamental]) andD -
the conversion is not necessitated by a
([expr.static.cast]).static_cast
A prvalue of an unscoped enumeration type can be converted to a prvalue of an integer type.
Insert a new paragraph immediately following [conv.integral] paragraph 1:
A prvalue of an unscoped enumeration type can be converted to a prvalue of an integer type.
Insert a new subclause in [depr] between [depr.local] and [depr.capture.this], containing a single paragraph:
Conversion from bool
to a character type [depr.conv.bool.char]
Integral conversion ([conv.integral])
from a prvalue of type
to a prvalue of character type ([basic.fundamental]) is deprecated,
unless it was necessitated by a
.