I've been looking into some of the new features of C++11 and am very impressed with some of them, particularly the user defined literals.
These allow you to define literals of the form 999_something
where something
controls what is done to the 999
to generate the literal. So no more having to use:
#define MEG * 1024 * 1024
int ten_meg = 10 M;
I was thinking this would be nice to implement underscores in large numbers, like 1_000_000_blah
which would match the readability of Perl, though the idea that Perl is somehow readable seems quite humorous to me :-)
It would also be handy for binary values like 1101_1110_b
and 0011_0011_1100_1111_b
.
Obviously because of the _
characters, these will need to be raw mode type, processing a C string, and I'm okay with that.
What I can't figure out is how to deliver a different type based on the operand size. For example:
1101_1110_b
should give a char
(assuming char
is 8-bit of course) while:
0011_0011_1100_1111_b
would deliver a 16-bit type.
I can get the length of the operand from within the literal operator function operator""
itself (by counting digit chars) but the return type seems to be fixed to the function so I can't return a different type based on this.
Can this be done with a single suffix _b
within the user defined types framework, or do I need to resort to splitting the types apart manually (_b8
, _b16
and so on) and provide mostly duplicate functions?
Literals are data used for representing fixed values. They can be used directly in the code. For example: 1 , 2.5 , 'c' etc. Here, 1 , 2.5 and 'c' are literals.
For example, // small integer short a = 12345; Here, a is a short integer variable. Note: short is equivalent to short int .
All the operators above except _r and _t are cooked literals.
Constants are variables that can't vary, whereas Literals are literally numbers/letters that indicate the value of a variable or constant.
You need to know the size oh your string, and the only way to achieve that is to have a parameter pack to use sizeof...
on. You should be able to achieve what you want with a variadic template operator""
:
#include <cstdint>
#include <type_traits>
template<char... String>
auto operator "" _b()
-> typename std::conditional<sizeof...(String) <= 8,
uint8_t,
typename std::conditional<sizeof...(String) <= 16,
uint16_t,
uint32_t
>::type
>::type
{
// Do whatever you want here
}
And here is a test case:
int main()
{
auto a = 10000001_b;
auto b = 100000001_b;
std::cout << std::boolalpha;
std::cout << std::is_same<decltype(a), uint8_t>::value << "\n"; // true
std::cout << std::is_same<decltype(b), uint16_t>::value << "\n"; // true
}
Unfortunately, that solution can't handle the digit separator. Moreover, the std::conditional
machinery is quite ugly. You could probably work something better with boost::mpl::vector
, boost::mpl::at
and some arithmetic operations.
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