1. Revision History
1.1. Revision 0
Initial Release 🎉
2. Motivation
Proposal [p0330r2] proposes literal suffixes for
and
. In
it, the question What about the fixed/least/max (unsigned) int types? is given regarding the
fixed/least/max integer types provided by
. As that paper has
decided to focus exclusively on
and
, this proposal will
instead focus on the fixed width integer literals. The problem of least/max
literals is left for another time and paper. The primary goal of this paper is
to replace the
/
macros found in
with user
defined literal suffixes.
As an example, one can see the results of the compiler results on godbolt.
#include <cstdint>void foo ( uint32_t ); void foo ( uint64_t ); void test () { // change this to 10ul and it fails to compile on MSVC // change this to 10ull and it fails to compile on GCC and Clang // The only safe thing to do is to use the UINTXX_C macros. auto x = 10 ; foo ( x ); }
Note: The author is more than willing to extend this paper’s scope for the least and max integer types, however the fixed width integer literals show promise of the least complex changes. Also we get to deprecate some C macros in the process and that’s always a good thing.
3. Design
The design for these literals suffixes is to permit explicitly sized
expressions when writing integer literals (e.g.,
).
These operators are declared in the namespace
where both
and
are inline namespaces. Access to
these operators can be gained with:
-
using namespace std :: literals -
using namespace integer_literals -
.using namespace std :: literals :: integer_literals
It is intended that these operators be placed into the
header.
3.1. Synopsis
The operator’s full specification is:
namespace std :: inline literals :: inline integer_literals { constexpr uint64_t operator "" u64 ( unsigned long long arg ); constexpr uint32_t operator "" u32 ( unsigned long long arg ); constexpr uint16_t operator "" u16 ( unsigned long long arg ); constexpr uint8_t operator "" u8 ( unsigned long long arg ); constexpr int64_t operator "" i64 ( unsigned long long arg ); constexpr int32_t operator "" i32 ( unsigned long long arg ); constexpr int16_t operator "" i16 ( unsigned long long arg ); constexpr int8_t operator "" i8 ( unsigned long long arg ); }
4. Examples
A small code example is presented below to show how the suffix can be used in code. (This code sample assumes that [P0645] has been added to the standard. Additionally as the author of [P1276], we use that here as well)
Note: This code sample does not attempt to solve the previously shown code in §2 Motivation, as this is easily solved elsewhere.
template < class ... Args > void println ( Args && ... args ) { std :: puts ( std :: format ( std :: forward < Args > ( args )...). c_str ()); } void main () { using namespace std :: literals ; println ( "1 + 2 = {}" , 1u32 + 2 ); println ( "1 - 2 = {}" , 1 i32 - 2 ); println ( "0011 AND 0101 is {:04b}" , 0 b0011u32 & 0 b0101 ); println ( "0011 XOR 0101 is {:04b}" , 0 b0011u32 ^ 0 b0101 ); println ( "0011 OR 0101 is {:04b}" , 0 b0011u32 | 0 b0101 ); println ( "One million is written as {}" , 1 ’000 ’000u 32 ) }
5. Wording
The following is wording for the library section.
namespace std :: inline literals :: inline integer_literals { constexpr uint64_t operator "" u64 ( unsigned long long arg ); }
-
Constraints
must fit in the rangearg arg <= numeric_limits < uint64_t >:: max () -
Returns
An integer of type
with the value given inuint64_t arg
namespace std :: inline literals :: inline integer_literals { constexpr uint32_t operator "" u32 ( unsigned long long arg ); }
-
Constraints
must fit in the rangearg arg <= numeric_limits < uint32_t >:: max () -
Returns
An integer of type
with the value given inuint32_t arg
namespace std :: inline literals :: inline integer_literals { constexpr uint16_t operator "" u16 ( unsigned long long arg ); }
-
Constraints
must fit in the rangearg arg <= numeric_limits < uint16_t >:: max () -
Returns
An integer of type
with the value given inuint16_t arg
namespace std :: inline literals :: inline integer_literals { constexpr uint8_t operator "" u8 ( unsigned long long arg ); }
-
Constraints
must fit in the rangearg arg <= numeric_limits < uint8_t >:: max () -
Returns
An integer of type
with the value given inuint8_t arg
namespace std :: inline literals :: inline integer_literals { constexpr int64_t operator "" i64 ( unsigned long long arg ); }
-
Constraints
must fit in the rangearg arg <= numeric_limits < int64_t >:: max () -
Returns
An integer of type
with the value given inint64_t arg
namespace std :: inline literals :: inline integer_literals { constexpr int32_t operator "" i32 ( unsigned long long arg ); }
-
Constraints
must fit in the rangearg arg <= numeric_limits < int32_t >:: max () -
Returns
An integer of type
with the value given inint32_t arg
namespace std :: inline literals :: inline integer_literals { constexpr int16_t operator "" i16 ( unsigned long long arg ); }
-
Constraints
must fit in the rangearg arg <= numeric_limits < int16_t >:: max () -
Returns
An integer of type
with the value given inint16_t arg
namespace std :: inline literals :: inline integer_literals { constexpr int8_t operator "" i8 ( unsigned long long arg ); }
-
Constraints
must fit in the rangearg arg <= numeric_limits < int8_t >:: max () -
Returns
An integer of type
with the value given inint8_t arg
5.1. Feature Testing
The
feature test macro should be added.