In our company in the code we use 64bit flag enums:
enum Flags : unsigned long long {
Flag1 = 1uLL<<0, // 1
//...
Flag40 = 1uLL<<40 // 1099511627776
};
And adding comments to see each flag decimal value even if we read the code in a text viewer. The problem is that nothing prevents a dev to put a wrong number in a comment.
There is a solution for this problem - a template with static_assert + a macro to use this approach easily - no need to use parenthesis and to add ::val everywhere:
template <unsigned long long i, unsigned long long j>
struct SNChecker{
static_assert(i == j, "Numbers not same!");
static const unsigned long long val = i;
};
#define SAMENUM(i, j) SNChecker<(i), (j)>::val
enum ET : unsigned long long {
ET1 = SAMENUM(1uLL<<2, 4),
ET2fail = SAMENUM(1uLL<<3, 4), // compile time error
ET4 = SAMENUM(1uLL<<40, 1099511627776uLL),
};
It all looks good, but we are not really fond of macros.
A question: can we do same with constexpr function, but without errors readability regression?
The closest solution I could think of is:
constexpr unsigned long long SameNum(unsigned long long i, unsigned long long j)
{
return (i == j) ? i : (throw "Numbers not same!");
}
but it generates an compile time error
error: expression '<throw-expression>' is not a constant-expression
instead of whatever I write in the static_assert
Edit:
The answer below is almost perfect except for one small regression: the call is a bit less pretty than using the macro.
One more approach (still worse than using static_assert but "prettier" in usage)
int NumbersNotSame() { return 0; }
constexpr unsigned long long SameNum(unsigned long long i, unsigned long long j)
{
return (i == j) ? i : (NumbersNotSame());
}
static_assert in constexpr function:
template<unsigned long long I, unsigned long long J>
constexpr unsigned long long SameNum()
{
static_assert(I == J, "numbers don't match");
return I;
}
enum ET : unsigned long long {
ET1 = SameNum<1uLL<<2, 4>(),
ET2fail = SameNum<1uLL<<3, 4>(), // compile time error
ET4 = SameNum<1uLL<<40, 1099511627776uLL>(),
};
Related
below you can find a part of my C++ code of a box class.
When I want to calculate the volume for
l=1039
b=3749
h=8473
I am expecting 33004122803.
Unfortunately I do not understand why only the first implementation (CalculateVolume1) gives the correct answer.
The other two calculations result in -1355615565.
Can someone please help me to understand why this is the case?
class Box{
private:
int l,b,h;
public:
//works
long long CalculateVolume1() { return (long long) l*b*h;}
// does not work
long long CalculateVolume2() { return long long v = l*b*h;}
//does not work
long long CalculateVolume3()
{
long long v = long long (l)* long long(b)* long long (h);
return v;
}
};
In the first one, (long long) l*b*h, the cast applies to l, as if it had been written ((long long)l)*b*h. So l gets converted to long long. And since one of the factors in the multiplication is long long, the other two are promoted to long long and the result of the multiplication is correct.
"Fixing" the syntactic errors in the second and third,
long long v = l*b*h;
here, the type of all three factors is int, so the multiplication is done on ints, and the result overflows.
long long v = (long long)l*(long long)b*(long long)h;
this is essentially the same as the first: all three factors are promoted to long long, this time by explicit casts on all three, so the result is calculated using long long arithmetic, and the result fits.
The problem with the second one as written is that you can't define a variable inside a return statement. So
return long long v = l; // illegal
should be:
long long v = l;
return v;
The problem with the third one as written is that a function-style cast has to have a name that's a single word:
long long v = int(l); // okay, but pointless
long long v = long long(l); // error, invalid name
could be:
typedef long long my_type;
long long v = my_type(l); // okay
While attempting to write the fastest factorial function that evaluates at run-time, I found myself questioning whether it is a good idea to declare the constant array f[] at the function level or at the unit level.
#include <stdint.h>
#include <cassert>
// uint64_t const f[21] = { 1,1,2,6,24,120,720,5040,40320,362880,3628800,39916800,479001600,6227020800, 87178291200, 1307674368000, 20922789888000, 355687428096000, 6402373705728000, 121645100408832000, 2432902008176640000 };
const uint64_t factorial(const uint8_t n) {
static uint64_t const f[21] = { 1,1,2,6,24,120,720,5040,40320,362880,3628800,39916800,479001600,6227020800, 87178291200, 1307674368000, 20922789888000, 355687428096000, 6402373705728000, 121645100408832000, 2432902008176640000 };
assert(n <= 20);
return f[n];
}
What are the pros and cons of each placement, assuming that f[] will be used only by the factorial() function ?
Is a constant, which is declared at the function level, created and destroyed each time the function is executed, like a non-const variable, or does the linker collect and put all constants in the .rodata section at compile-time?
In my humble opinion the best is to let the compiler decide and do evrything with constexpr. The compiler will make the best decision for you.
And because the number of factorials that will fit into an unsigned 64 bit value is very low (21), a compile time array will use mainly only 21*8 = 168 bytes.
168 bytes
That number is that low that we can build easily a compile time constexpr std::array and stop all further considerations.
Really everything can be done at compile time.
We will first define the default approach for calculation a factorial as a constexpr function:
constexpr unsigned long long factorial(unsigned long long n) noexcept {
return n == 0ull ? 1 : n * factorial(n - 1ull);
}
With that, factorials can easily be calculated at compile time. Then, we fill a std::array with all factorials. We use also a constexpr and make it a template with a variadic parameter pack.
We use std::integer_sequence to create a factorials for indices 0,1,2,3,4,5, ....
That is straigtforward and not complicated:
template <size_t... ManyIndices>
constexpr auto generateArrayHelper(std::integer_sequence<size_t, ManyIndices...>) noexcept {
return std::array<unsigned long long, sizeof...(ManyIndices)>{ { factorial(ManyIndices)... } };
};
This function will be fed with an integer sequence 0,1,2,3,4,... and return a std::array<unsigned long long, ...> with the corresponding factorials.
We know that we can store maximum 21 values. And therefore we make a next function, that will call the above with the integer sequence 1,2,3,4,...,20,21, like so:
constexpr auto generateArray()noexcept {
return generateArrayHelper(std::make_integer_sequence<size_t, MaxIndexFor64BitValue>());
}
And now, finally,
constexpr auto Factorial = generateArray();
will give us a compile-time std::array<unsigned long long, 21> with the name Factorial containing all factorials. And if we need the i'th factorial, then we can simply write Factorial[i]. There will be no calculation at runtime.
I do not think that there is a faster way to calculate a factorial.
Please see the complete program below:
#include <iostream>
#include <array>
#include <utility>
// ----------------------------------------------------------------------
// All the below will be calculated at compile time
// constexpr factorial function
constexpr unsigned long long factorial(unsigned long long n) noexcept {
return n == 0ull ? 1 : n * factorial(n - 1ull);
}
// We will automatically build an array of factorials at compile time
// Generate a std::array with n elements
template <size_t... ManyIndices>
constexpr auto generateArrayHelper(std::integer_sequence<size_t, ManyIndices...>) noexcept {
return std::array<unsigned long long, sizeof...(ManyIndices)>{ { factorial(ManyIndices)... } };
};
// Max index for factorials for an 64bit unsigned value
constexpr size_t MaxIndexFor64BitValue = 21;
// Generate the required number of elements
constexpr auto generateArray()noexcept {
return generateArrayHelper(std::make_integer_sequence<size_t, MaxIndexFor64BitValue>());
}
// This is an constexpr array of all factorials numbers
constexpr auto Factorial = generateArray();
// All the above was compile time
// ----------------------------------------------------------------------
// Test function
int main() {
for (size_t i{}; i < MaxIndexFor64BitValue; ++i)
std::cout << i << '\t' << Factorial[i] << '\n';
return 0;
}
Developed, compiled and tested with Microsoft Visual Studio Community 2019, Version 16.8.2
Additionally compiled and tested with gcc 10.2 and clang 11.0.1
Language: C++17
I have code like this which is meant to target various compilers and platforms:
long value = obtainLongValue();
if(value <= 0)
handleError();
if((unsigned long)value >= (size_t)-1)
handleError();
size_t valueAsSizeT = value;
char* buffer = new char[value + 1];
Thechnically size_t can be smaller that unsigned long or the other way around or they can be of the same size.
On some targets both size_t and unsigned long are 64-bit and the code actually checks something and compiles cleanly. Yet on other targets size_t is 64-bit and unsigned long is 32-bit and for such platforms the check is meaningless - long is never long enough to overflow size_t - and so gcc emits a warning when used with -WExtra:
warning: comparison is always false due to limited range of data type [-Wtype-limits]
gcc is technically correct on those targets, but I need this check in place just in case.
How do I keep the check and have this code compiled cleanly with gcc?
Use template and specialization:
template <bool = sizeof(unsigned long) <= sizeof(std::size_t)>
constexpr bool CheckLongLessThanMaxSizeT(unsigned long value)
{
return true;
}
template <>
constexpr bool CheckLongLessThanMaxSizeT<false>(unsigned long value)
{
return value <= static_cast<std::size_t>(-1);
}
Let's say that you are using <cstdint> and types like std::uint8_t and std::uint16_t, and want to do operations like += and *= on them. You'd like arithmetic on these numbers to wrap around modularly, like typical in C/C++. This ordinarily works, and you find experimentally works with std::uint8_t, std::uint32_t and std::uint64_t, but not std::uint16_t.
Specifically, multiplication with std::uint16_t sometimes fails spectacularly, with optimized builds producing all kinds of weird results. The reason? Undefined behavior due to signed integer overflow. The compiler is optimizing based upon the assumption that undefined behavior does not occur, and so starts pruning chunks of code from your program. The specific undefined behavior is the following:
std::uint16_t x = UINT16_C(0xFFFF);
x *= x;
The reason is C++'s promotion rules and the fact that you, like almost everyone else these days, are using a platform on which std::numeric_limits<int>::digits == 31. That is, int is 32-bit (digits counts bits but not the sign bit). x gets promoted to signed int, despite being unsigned, and 0xFFFF * 0xFFFF overflows for 32-bit signed arithmetic.
Demo of the general problem:
// Compile on a recent version of clang and run it:
// clang++ -std=c++11 -O3 -Wall -fsanitize=undefined stdint16.cpp -o stdint16
#include <cinttypes>
#include <cstdint>
#include <cstdio>
int main()
{
std::uint8_t a = UINT8_MAX; a *= a; // OK
std::uint16_t b = UINT16_MAX; b *= b; // undefined!
std::uint32_t c = UINT32_MAX; c *= c; // OK
std::uint64_t d = UINT64_MAX; d *= d; // OK
std::printf("%02" PRIX8 " %04" PRIX16 " %08" PRIX32 " %016" PRIX64 "\n",
a, b, c, d);
return 0;
}
You'll get a nice error:
main.cpp:11:55: runtime error: signed integer overflow: 65535 * 65535
cannot be represented in type 'int'
The way to avoid this, of course, is to cast to at least unsigned int before multiplying. Only the exact case where the number of bits of the unsigned type exactly equals half the number of bits of int is problematic. Any smaller would result in the multiplication being unable to overflow, as with std::uint8_t; any larger would result in the type exactly mapping to one of the promotion ranks, as with std::uint64_t matching unsigned long or unsigned long long depending on platform.
But this really sucks: it requires knowing which type is problematic based upon the size of int on the current platform. Is there some better way by which undefined behavior with unsigned integer multiplication can be avoided without #if mazes?
Some template metaprogramming with SFINAE, perhaps.
#include <type_traits>
template <typename T, typename std::enable_if<std::is_unsigned<T>::value && (sizeof(T) <= sizeof(unsigned int)) , int>::type = 0>
T safe_multiply(T a, T b) {
return (unsigned int)a * (unsigned int)b;
}
template <typename T, typename std::enable_if<std::is_unsigned<T>::value && (sizeof(T) > sizeof(unsigned int)) , int>::type = 0>
T safe_multiply(T a, T b) {
return a * b;
}
Demo.
Edit: simpler:
template <typename T, typename std::enable_if<std::is_unsigned<T>::value, int>::type = 0>
T safe_multiply(T a, T b) {
typedef typename std::make_unsigned<decltype(+a)>::type typ;
return (typ)a * (typ)b;
}
Demo.
Here's a relatively simple solution, which forces a promotion to unsigned int instead of int for unsigned type narrower than an int. I don't think any code is generated by promote, or at least no more code than the standard integer promotion; it will just force multiplication etc. to use unsigned ops instead of signed ones:
#include <type_traits>
// Promote to unsigned if standard arithmetic promotion loses unsignedness
template<typename integer>
using promoted =
typename std::conditional<std::numeric_limits<decltype(integer() + 0)>::is_signed,
unsigned,
integer>::type;
// function for template deduction
template<typename integer>
constexpr promoted<integer> promote(integer x) { return x; }
// Quick test
#include <cstdint>
#include <iostream>
#include <limits>
int main() {
uint8_t i8 = std::numeric_limits<uint8_t>::max();
uint16_t i16 = std::numeric_limits<uint16_t>::max();
uint32_t i32 = std::numeric_limits<uint32_t>::max();
uint64_t i64 = std::numeric_limits<uint64_t>::max();
i8 *= promote(i8);
i16 *= promote(i16);
i32 *= promote(i32);
i64 *= promote(i64);
std::cout << " 8: " << static_cast<int>(i8) << std::endl
<< "16: " << i16 << std::endl
<< "32: " << i32 << std::endl
<< "64: " << i64 << std::endl;
return 0;
}
This article regarding a C solution to the case of uint32_t * uint32_t multiplication on a system in which int is 64 bits has a really simple solution that I hadn't thought of: 32 bit unsigned multiply on 64 bit causing undefined behavior?
That solution, translated to my problem, is simple:
// C++
static_cast<std::uint16_t>(1U * x * x)
// C
(uint16_t) (1U * x * x)
Simply involving 1U in the left side of the chain of arithmetic operations like that will promote the first parameter to the larger rank of unsigned int and std::uint16_t, then so on down the chain. The promotion will ensure that the answer is both unsigned and that the requested bits remain present. The final cast then reduces it back to the desired type.
This is really simple and elegant, and I wish I had thought of it a year ago. Thank you to everyone who responded before.
I'm using a well known template to allow binary constants
template< unsigned long long N >
struct binary
{
enum { value = (N % 10) + 2 * binary< N / 10 > :: value } ;
};
template<>
struct binary< 0 >
{
enum { value = 0 } ;
};
So you can do something like binary<101011011>::value. Unfortunately this has a limit of 20 digits for a unsigned long long.
Does anyone have a better solution?
Does this work if you have a leading zero on your binary value? A leading zero makes the constant octal rather than decimal.
Which leads to a way to squeeze a couple more digits out of this solution - always start your binary constant with a zero! Then replace the 10's in your template with 8's.
The approaches I've always used, though not as elegant as yours:
1/ Just use hex. After a while, you just get to know which hex digits represent which bit patterns.
2/ Use constants and OR or ADD them. For example (may need qualifiers on the bit patterns to make them unsigned or long):
#define b0 0x00000001
#define b1 0x00000002
: : :
#define b31 0x80000000
unsigned long x = b2 | b7
3/ If performance isn't critical and readability is important, you can just do it at runtime with a function such as "x = fromBin("101011011");".
4/ As a sneaky solution, you could write a pre-pre-processor that goes through your *.cppme files and creates the *.cpp ones by replacing all "0b101011011"-type strings with their equivalent "0x15b" strings). I wouldn't do this lightly since there's all sorts of tricky combinations of syntax you may have to worry about. But it would allow you to write your string as you want to without having to worry about the vagaries of the compiler, and you could limit the syntax trickiness by careful coding.
Of course, the next step after that would be patching GCC to recognize "0b" constants but that may be an overkill :-)
C++0x has user-defined literals, which could be used to implement what you're talking about.
Otherwise, I don't know how to improve this template.
template<unsigned int p,unsigned int i> struct BinaryDigit
{
enum { value = p*2+i };
typedef BinaryDigit<value,0> O;
typedef BinaryDigit<value,1> I;
};
struct Bin
{
typedef BinaryDigit<0,0> O;
typedef BinaryDigit<0,1> I;
};
Allowing:
Bin::O::I::I::O::O::value
much more verbose, but no limits (until you hit the size of an unsigned int of course).
You can add more non-type template parameters to "simulate" additional bits:
// Utility metafunction used by top_bit<N>.
template <unsigned long long N1, unsigned long long N2>
struct compare {
enum { value = N1 > N2 ? N1 >> 1 : compare<N1 << 1, N2>::value };
};
// This is hit when N1 grows beyond the size representable
// in an unsigned long long. It's value is never actually used.
template<unsigned long long N2>
struct compare<0, N2> {
enum { value = 42 };
};
// Determine the highest 1-bit in an integer. Returns 0 for N == 0.
template <unsigned long long N>
struct top_bit {
enum { value = compare<1, N>::value };
};
template <unsigned long long N1, unsigned long long N2 = 0>
struct binary {
enum {
value =
(top_bit<binary<N2>::value>::value << 1) * binary<N1>::value +
binary<N2>::value
};
};
template <unsigned long long N1>
struct binary<N1, 0> {
enum { value = (N1 % 10) + 2 * binary<N1 / 10>::value };
};
template <>
struct binary<0> {
enum { value = 0 } ;
};
You can use this as before, e.g.:
binary<1001101>::value
But you can also use the following equivalent forms:
binary<100,1101>::value
binary<1001,101>::value
binary<100110,1>::value
Basically, the extra parameter gives you another 20 bits to play with. You could add even more parameters if necessary.
Because the place value of the second number is used to figure out how far to the left the first number needs to be shifted, the second number must begin with a 1. (This is required anyway, since starting it with a 0 would cause the number to be interpreted as an octal number.)
Technically it is not C nor C++, it is a GCC specific extension, but GCC allows binary constants as seen here:
The following statements are identical:
i = 42;
i = 0x2a;
i = 052;
i = 0b101010;
Hope that helps. Some Intel compilers and I am sure others, implement some of the GNU extensions. Maybe you are lucky.
A simple #define works very well:
#define HEX__(n) 0x##n##LU
#define B8__(x) ((x&0x0000000FLU)?1:0)\
+((x&0x000000F0LU)?2:0)\
+((x&0x00000F00LU)?4:0)\
+((x&0x0000F000LU)?8:0)\
+((x&0x000F0000LU)?16:0)\
+((x&0x00F00000LU)?32:0)\
+((x&0x0F000000LU)?64:0)\
+((x&0xF0000000LU)?128:0)
#define B8(d) ((unsigned char)B8__(HEX__(d)))
#define B16(dmsb,dlsb) (((unsigned short)B8(dmsb)<<8) + B8(dlsb))
#define B32(dmsb,db2,db3,dlsb) (((unsigned long)B8(dmsb)<<24) + ((unsigned long)B8(db2)<<16) + ((unsigned long)B8(db3)<<8) + B8(dlsb))
B8(011100111)
B16(10011011,10011011)
B32(10011011,10011011,10011011,10011011)
Not my invention, I saw it on a forum a long time ago.