There are known ways to manipulate the type of an integer literal
0L; // long 3U; // unsigned integer 1LL; // long long
What I need is a way to initialize an integer literal to std::size_t
. I supposed that doing
2U; // unsigned int
would be enough, but I still get a compiler error when calling a function template that expects two arguments of the same integral type (no matching function to call for func(unsigned int, size_t
)
I know/verified that explicitly casting ( static_cast<std::size_t>(1)
) the first argument solves the problem but I'm asking if there's a prettier solution
EDIT
the function has a signature
template <class T> const T& func(const T& a, const T& b);
EDIT2
I don't know if this question is to "blame" but I'm happy to announce that this is upcoming (cudos @malat for mentioning this in the comments)
It will get promoted to type int because type int can represent all values of type size_t and rank of size_t, being a synonym for unsigned short, is lower than the rank of int. Since the maximum values of size_t, and int are the same, the computation causes a signed overflow, causing undefined behavior.
Integer literals begin with a digit and have no fractional parts or exponents. You can specify integer literals in decimal, binary, octal, or hexadecimal form. You can optionally specify an integer literal as unsigned, and as a long or long long type, by using a suffix.
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.
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.
There is no such standard facility. C99 and C++11 implementations do have such macros in <stdint.h>
/<cstdint>
. But even there, the macros are only defined for the stdint.h
types, which do not include size_t
.
You could define a user-defined literal operator:
constexpr std::size_t operator "" _z ( unsigned long long n ) { return n; } auto sz = 5_z; static_assert( std::is_same< decltype( sz ), std::size_t >::value, "" );
The constexpr
is necessary to use it in array bounds int arr[ 23_z ]
or case 9_z:
labels.
Most would probably consider the lack of macros to be an advantage :) .
Cuteness aside, the best way is to use brace initialization: std::size_t{ 42 }
. This is not equivalent to std::size_t( 42 )
which is like a nasty C cast — presumably what you were avoiding with static_cast
. Quite the opposite: the braces require that the value inside is exactly representable in the targeted type. So, char{ 300 }
and std::size_t{ -1 }
are both ill-formed.
Braces and parens look similar, but they're polar opposites in safety when initializing temporaries. Braces are safer than the literal operator could ever be, since unlike a function they can discriminate compile-time values.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With