Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Initialize integer literal to std::size_t

Tags:

c++

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)

like image 656
Nikos Athanasiou Avatar asked Mar 12 '14 08:03

Nikos Athanasiou


People also ask

Can you add Size_t to int?

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.

What is an integer literal in C++?

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.

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

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.

like image 190
Potatoswatter Avatar answered Sep 17 '22 15:09

Potatoswatter