Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Fixed-width integer literals in C++?

C++11 first introduced support for defining new literals into C++ by means of user-defined literals. Does C++11 or later also predefine suffixes for fixed-width integer literals for types in <cstdint>?

like image 914
jotik Avatar asked Apr 04 '16 15:04

jotik


People also ask

What is a fixed width integer?

Fixed-width integers are integral types with a fixed number of bits. The C++ standard only specifies a minimum byte count for types such as short , int and long . Fixed-width integers guarantee a specific size, but their use can have an impact on portability, since they are not supported by all platforms.

What is int16_t in C?

For example, the name int16_t indicates a 16-bit signed integer type and the name uint32_t indicates a 32-bit unsigned integer type. To make these names available to a program, include the inttypes.

What is the value of integer literal 013?

It is extremely easy to inadvertently create an integer object with the wrong value, because '013' means 'decimal 11', not 'decimal 13', to the Python language itself, which is not the meaning that most humans would assign to this literal.

What is an int literal?

Integer literals are numbers that do not have a decimal point or an exponential part. They can be represented as: Decimal integer literals. Hexadecimal integer literals.


1 Answers

No. As of C++14 the only literal suffixes defined by the standard are provided by <chrono>, <complex> and <string> headers in the standard library. The <chrono> header defines the h, min, s, ms, us, ns suffixes for time durations, <complex> defines the i, il and if suffixes for imaginary numbers, and <string> defines the s suffix for basic_string literals.

However, one can easily define their own fixed-width literals like this:

#include <cstdint>

constexpr std::int8_t operator "" _int8(unsigned long long v)
{ return static_cast<std::int8_t>(v); }

constexpr std::uint8_t operator "" _uint8(unsigned long long v)
{ return static_cast<std::uint8_t>(v); }

constexpr std::int16_t operator "" _int16(unsigned long long v)
{ return static_cast<std::int16_t>(v); }

constexpr std::uint16_t operator "" _uint16(unsigned long long v)
{ return static_cast<std::uint16_t>(v); }

constexpr std::int32_t operator "" _int32(unsigned long long v)
{ return static_cast<std::int32_t>(v); }

constexpr std::uint32_t operator "" _uint32(unsigned long long v)
{ return static_cast<std::uint32_t>(v); }

constexpr std::int64_t operator "" _int64(unsigned long long v)
{ return static_cast<std::int64_t>(v); }

constexpr std::uint64_t operator "" _uint64(unsigned long long v)
{ return static_cast<std::uint64_t>(v); }

constexpr std::int_fast8_t operator "" _int_fast8(unsigned long long v)
{ return static_cast<std::int_fast8_t>(v); }

constexpr std::uint_fast8_t operator "" _uint_fast8(unsigned long long v)
{ return static_cast<std::uint_fast8_t>(v); }

constexpr std::int_fast16_t operator "" _int_fast16(unsigned long long v)
{ return static_cast<std::int_fast16_t>(v); }

constexpr std::uint_fast16_t operator "" _uint_fast16(unsigned long long v)
{ return static_cast<std::uint_fast16_t>(v); }

constexpr std::int_fast32_t operator "" _int_fast32(unsigned long long v)
{ return static_cast<std::int_fast32_t>(v); }

constexpr std::uint_fast32_t operator "" _uint_fast32(unsigned long long v)
{ return static_cast<std::uint_fast32_t>(v); }

constexpr std::int_fast64_t operator "" _int_fast64(unsigned long long v)
{ return static_cast<std::int_fast64_t>(v); }

constexpr std::uint_fast64_t operator "" _uint_fast64(unsigned long long v)
{ return static_cast<std::uint_fast64_t>(v); }

constexpr std::int_least8_t operator "" _int_least8(unsigned long long v)
{ return static_cast<std::int_least8_t>(v); }

constexpr std::uint_least8_t operator "" _uint_least8(unsigned long long v)
{ return static_cast<std::uint_least8_t>(v); }

constexpr std::int_least16_t operator "" _int_least16(unsigned long long v)
{ return static_cast<std::int_least16_t>(v); }

constexpr std::uint_least16_t operator "" _uint_least16(unsigned long long v)
{ return static_cast<std::uint_least16_t>(v); }

constexpr std::int_least32_t operator "" _int_least32(unsigned long long v)
{ return static_cast<std::int_least32_t>(v); }

constexpr std::uint_least32_t operator "" _uint_least32(unsigned long long v)
{ return static_cast<std::uint_least32_t>(v); }

constexpr std::int_least64_t operator "" _int_least64(unsigned long long v)
{ return static_cast<std::int_least64_t>(v); }

constexpr std::uint_least64_t operator "" _uint_least64(unsigned long long v)
{ return static_cast<std::uint_least64_t>(v); }

constexpr std::intmax_t operator "" _intmax(unsigned long long v)
{ return static_cast<std::intmax_t>(v); }

constexpr std::uintmax_t operator "" _uintmax(unsigned long long v)
{ return static_cast<std::uintmax_t>(v); }

constexpr std::intptr_t operator "" _intptr(unsigned long long v)
{ return static_cast<std::intptr_t>(v); }

constexpr std::uintptr_t operator "" _uintptr(unsigned long long v)
{ return static_cast<std::uintptr_t>(v); }

Warning: The above code will silently give the wrong result if used on literals which don't fit into unsigned long long, as well as overflow if the literal value, doesn't fit into the requested type, e.g. 999_int8. A better implementation (GPL-3 licensed) would probably have to parse the literal character-by-character and static_assert on overflow, like this.

The downside of using user defined literals is that one needs to prefix the suffixes with an underscore _, because suffixes without the underscore are reserved for future standardization according to §17.6.4.3.4.

like image 90
jotik Avatar answered Oct 10 '22 15:10

jotik