I have a function that we use to enforce type matches when setting into a buffer:
void SetUInt8(size_checker<uint8_t> val)
{
// make some static checks
}
usually, it is invoked like this:
// compile error, since you might mean to call the SetUInt() function
int myvar = 10;
SetUInt8(myvar);
// works fine
int8_t myvar = 1;
SetUInt8(myvar);
This call causes a warning because the 30 is interpreted as an int:
SetUInt8(30);
But I really want this to be OK since 30 < 256. Ideally, I would like the invocation not to have to change, but I have come up with the following:
template<size_t T>
void SetUInt8()
{
ASSERT(T < 256);
// do other stuff
}
Which of course would be used like:
SetUInt8<30>();
Alternatively, I can cast when calling the function:
SetUInt8(uint8_t(30U));
Is there another way around the issue of 30 being converted to an int, or detecting its actual value if its a compile time constant?
The best thought I have is a template, static-asserted function that static_casts for you:
template<size_t size>
void SetUInt8()
{
BOOST_STATIC_ASSERT(size < 256);
SetUInt8(static_cast<uint8_t>(size));
}
Call it like you did: SetUInt8<50>();
Since it should hopefully always be inlined there's no performance overhead and it does compile-time range checking. Better would be if the compiler were smart enough to not warn when the value clearly fits in the range of the smaller type.
Related
#include <array>
int value1(int param) {
return param * 2;
}
constexpr int value2(int param) {
return param * 2;
}
int main() {
const int i = 10;
std::array<int, value1(i)> starr1 = {}; // 1
std::array<int, value2(i)> starr2 = {}; // 2
return 0;
}
2 is okay, but 1 gives a compile error because std::array has to make static size array. value2() returns compile-time constant value because of constexpr keyword.
So, how does the compiler infer that value2(i) is compile-time constant? Does it call the function value2() while compiling?
const int value1(int param) {
return param * 2;
}
int main() {
const int i = 10;
std::array<int, value1(i)> starr1 = {}; // 3
return 0;
}
>>> error: call to non-constexpr function ‘const int value1(int)’
Also, 3 still tgives a compile error. Is value1(i) not compile-time constant even though const keyword is applied to the function value1()?
So, how compiler infer value2(i) is compile-time constant?
It doesn't infer that. You state that explicitly when you annotate it with constexpr. It might infer that for functions not marked with constexpr, though. This still won't allow you to use their results in compile-time expressions, and is only used as an optimization strategy.
Does it call the function value2() while compiling?
In a sense, yes. It's probably closer to interpreting it directly, since I don't think any compiler actually compiles that function for the purposes of executing it during the build. What matters is that it's able to establish its result before the entire program is built and ran, and that it can use that result to e.g. determine the size of your array when generating the code.
Is value1(i) not compile constant even though const keyword is applied to the function value1()?
It's not. const only applies to the return type (and in this case, it's effectively useless), not the evaluation possibility in compile-time.
I have a function which executes a bunch of tests. Whenever a new test is created, the function gets one or two more lines. And - the result is pushed back into an array. So it goes something like this (simplified):
void foo(int *results) {
auto index { 0 };
results[i++] = test_1(some, args, here);
results[i++] = test_1(some, other_args, here);
results[i++] = test_2(some, args, here);
results[i++] = test_3(some, args, here);
// etc. etc.
}
void bar() {
auto results = new int/* magic */];
foo(results);
}
I want to use the number of statements in this function to allocate space for the results (the line in bar()). I cannot use a dynamically-reallocated structure like an std::vector or a list etc. - since I am precluded from allocating any memory due to hardware restrictions.
Now, I could just manually count the lines - and this would work. But then whenever I add another test I would have to remember to update the magical constant.
Is there some way to do the counting with the result usable for the "magic" expression?
Note: Since I'm a scrupulous man with no dignity, I am willing to stoop to the use of macros.
Speaking of macro hackery:
#include <iostream>
#define ADD_TEST(X) do { results[i++] = (X); (void)__COUNTER__; } while (0)
const int foo_start = __COUNTER__;
void foo(int *results) {
int i = 0;
ADD_TEST(100);
ADD_TEST(200);
ADD_TEST(300);
}
const int foo_end = __COUNTER__;
int main() {
int results[foo_end - foo_start - 1];
foo(results);
for (int i : results) {
std::cout << i << '\n';
}
}
It's slightly awful and __COUNTER__ is a non-standard extension in GCC and other compilers, but hey, it works.
The advantage is that it doesn't use any fancy C++ features, so in principle it should be compatible with older compilers and even C.
As you haven't specified any language version, though, did tag it with constexpr, I've solved this making use of C++17. This without any dirty macros. Instead, I'm relying on CTAD (Constructor template argument deduction).
First of all, I've assumed your functions are constexpr. That way, everything can be done at compile-time. (In the resulting code, you don't even see memory being used for the array.
constexpr int test_1(int a, int b, int c)
{
return a + b + c;
}
constexpr int test_2(int a, int b, int c)
{
return a * b * c;
}
This isn't strictly needed, however, it can move unneeded calculations to compile time. It also allows propagating constexpr upto the final variable. That way, you could guarantee that none of the calculations will happen at run-time.
static constexpr auto myArr = createFilledArray();
However, the most important part is CTAD. A new C++17 feature that allows deducing the template arguments of your class based on the values that are passed at the constructor.
Instead of first creating an array, I create the array directly with all the different values that you pass to it. Since you haven't provided any arguments in your example, I assume they are known at compile time, which is again required for the constexpr waterfall. However, more importantly, I assume the number of elements is known at compile time.
By constructing all arguments when calling the constructor of std::array, there is no need for specifying its template arguments (note also the auto as return type). This gets deduced as std::array<int, 3> for this example.
constexpr auto createFilledArray(){
std::array a
{
test_1(1, 2, 3),
test_1(4, 5, 6),
test_2(7, 8, 9),
};
return a;
}
int main(int, char**)
{
return myArr.size(); // Returns 3
}
Code at compiler explorer
From what I'm aware, there is a proposal for C++20 that is intended to make std::vector constexpr. However, none of the compilers I've tested at compiler explorer support this. This will most likely allow you to write code based on std::vector and use that at compile time. In other words, the allocated memory that represents your data, will be part of your executable.
A quick attempt of what your code could look like can be found here at compiler explorer. (However, it ain't compiling at this point)
This is a C++ programming code to display the values of array1 and array2 but I am getting a compile time error as 'Constant Expression Required'. Please Help
void display(const int const1 = 5)
{
const int const2 = 5;
int array1[const1];
int array2[const2];
for(int i = 1 ; i < 5 ; i++)
{
array1[i] = i;
array2[i] = i * 10;
std::cout << array1[i] << std::endl;
}
}
void main()
{
display(5);
}
In C++, const is not always constexpr. Back in the days, constexpr didn't exist, so the only way of having a compile time constant was to either use const with a literal, or to use enum, because both of these are easy for the compiler to check the value.
However, in C++11, we added constexpr, which guaranties that a constexpr variable has a value available at compile-time, and state that constexpr function can be evaluated aat compile time if all arguments are constexpr too.
In your code, you can write your variable const2 like this:
void display(const int const1=5)
{
constexpr int const2 = 5;
// ...
}
Now your code is much more expressive about what you are doing. instead of relying that the const may be available at compile time, you say "this variable has a value known at compile time, here's the value".
However, if you try to change const1, you'll get an error. Parameters, even with default value always as a value known at runtime. If the value is only known at runtime, you can't use it in template parameters or array size.
If you want your function to be able to receive the value const1 as a constant expression from where you can receive it as a template parameter, since template parameters are always known at compile time.
template<int const1 = 5>
void display()
{
constexpr int const2 = 5;
int array1[const1];
int array2[const2];
}
You will have to call your function like that:
// const1 is 5
display();
// const1 is 10
display<10>();
If you want to know more about templates, go check Function templates, or this tutorial
My actual question is it really possible to compare values contained in two void pointers, when you actually know that these values are the same type? For example int.
void compVoids(void *firstVal, void *secondVal){
if (firstVal < secondVal){
cout << "This will not make any sense as this will compare addresses, not values" << endl;
}
}
Actually I need to compare two void pointer values, while outside the function it is known that the type is int. I do not want to use comparison of int inside the function.
So this will not work for me as well: if (*(int*)firstVal > *(int*)secondVal)
Any suggestions?
Thank you very much for help!
In order to compare the data pointed to by a void*, you must know what the type is. If you know what the type is, there is no need for a void*. If you want to write a function that can be used for multiple types, you use templates:
template<typename T>
bool compare(const T& firstVal, const T& secondVal)
{
if (firstVal < secondVal)
{
// do something
}
return something;
}
To illustrate why attempting to compare void pointers blind is not feasible:
bool compare(void* firstVal, void* secondVal)
{
if (*firstVal < *secondVal) // ERROR: cannot dereference a void*
{
// do something
}
return something;
}
So, you need to know the size to compare, which means you either need to pass in a std::size_t parameter, or you need to know the type (and really, in order to pass in the std::size_t parameter, you have to know the type):
bool compare(void* firstVal, void* secondVal, std::size_t size)
{
if (0 > memcmp(firstVal, secondVal, size))
{
// do something
}
return something;
}
int a = 5;
int b = 6;
bool test = compare(&a, &b, sizeof(int)); // you know the type!
This was required in C as templates did not exist. C++ has templates, which make this type of function declaration unnecessary and inferior (templates allow for enforcement of type safety - void pointers do not, as I'll show below).
The problem comes in when you do something (silly) like this:
int a = 5;
short b = 6;
bool test = compare(&a, &b, sizeof(int)); // DOH! this will try to compare memory outside the bounds of the size of b
bool test = compare(&a, &b, sizeof(short)); // DOH! This will compare the first part of a with b. Endianess will be an issue.
As you can see, by doing this, you lose all type safety and have a whole host of other issues you have to deal with.
It is definitely possible, but since they are void pointers you must specify how much data is to be compared and how.
The memcmp function may be what you are looking for. It takes two void pointers and an argument for the number of bytes to be compared and returns a comparison. Some comparisons, however, are not contingent upon all of the data being equal. For example: comparing the direction of two vectors ignoring their length.
This question doesn't have a definite answer unless you specify how you want to compare the data.
You need to dereference them and cast, with
if (*(int*) firstVal < *(int*) secondVal)
Why do you not want to use the int comparison inside the function, if you know that the two values will be int and that you want to compare the int values that they're pointing to?
You mentioned a comparison function for comparing data on inserts; for a comparison function, I recommend this:
int
compareIntValues (void *first, void *second)
{
return (*(int*) first - *(int*) second);
}
It follows the convention of negative if the first is smaller, 0 if they're equal, positive if the first is larger. Simply call this function when you want to compare the int data.
yes. and in fact your code is correct if the type is unsigned int. casting int values to void pointer is often used even not recommended.
Also you could cast the pointers but you have to cast them directly to the int type:
if ((int)firstVal < (int)secondVal)
Note: no * at all.
You may have address model issues doing this though if you build 32 and 64 bits. Check the intptr_t type that you could use to avoid that.
if ((intptr_t)firstVal < (intptr_t)secondVal)
I'm trying to create a compile-time bit mask using metaprograming techniques, my idea is to create something like this:
unsigned int Mask3 = Mask<2>(); // value = 0x03 = b00000000000000000000000000000011
unsigned int Mask3 = Mask<3>(); // value = 0x07 = b00000000000000000000000000000111
unsigned int Mask3 = Mask<7>(); // value = 0x7F = b00000000000000000000000001111111
The code that I'm trying is this:
template <const unsigned int N> const unsigned int Mask()
{
if (N <= 1)
{
return 1;
}
else
{
return ((1 << N) | Mask<N - 1>());
}
}
return 1;
But it result in tons pairs of warnings:
warning C4554: '<<' : check operator precedence for possible error
warning C4293: '<<' : shift count negative or too big
And in the end, the compile error:
error C1202: recursive type or function dependency context too complex.
So, I deduce that the recursivity never ends and falls into a compiler infinite loop but I'm don't understanding WHY.
As has already been pointed out, you're depending on a runtime check to
stop a compile time recursion, which can't work. More importantly,
perhaps, for what you want to do, is that you're defining a function,
which has no value until you call it. So even after you stop the
recursion with a specialization, you still have a nested sequence of
functions, which will be called at runtime.
If you want full compile time evaluation, you must define a static data
member of a class template, since that's the only way a compile time
constant can appear in a template. Something like:
template <unsigned int N>
struct Mask
{
static unsigned int const value = (1 << (N - 1)) | Mask<N - 1>::value;
};
template <>
struct Mask<0>
{
static unsigned int const value = 0;
};
(I've also corrected the numerical values you got wrong.)
Of course, you don't need anything this complicated. The following
should do the trick:
template <unsigned int N>
struct Mask
{
static unsigned int const value = (1 << (N + 1)) - 1;
};
template <>
struct Mask<0>
{
static unsigned int const value = 0;
};
(You still need the specialization for 0. Otherwise, 0 means all bits
set.)
Finally, of course: to access the value, you need to write something
like Mask<3>::value. (You might want to wrap this in a macro.)
It doesn't need to be recursive. This should work just fine :
template <const unsigned int N> const unsigned int Mask()
{
return ((1 << N) - 1);
}
It doesn't even need to be a template really. An (inlined) function is ok.
Note that if you want to support any value of N, specifically N >= sizeof(unsigned int) * CHAR_BIT, you probably want to treat those as a special case.
A template is created at compile time, but you are relying on run time behavior to stop the recursion.
For example, if you instantiate Mask<2>, it is going to use Mask<1>, which is going to use Mask<0>, which is going to use Mask<-1>, etc.
You have a runtime check for N being <= 1, but this doesn't help when it's compiling. It still creates an infinite sequence of functions.
To blunt template instantiation recursion you need to introduce one explicit specialization:
template <0> const unsigned int Mask()
{
return 1;
}
Your recursion never ends, because compiler tries to generate template implementation for both if-branches. So, when it generates Mask<0> it also generates Mask<0xffffffff> and so on
C++11 -- no recursion or templates:
constexpr unsigned mask(unsigned N) { return unsigned(~(-1<<N)); }
So far the answers only addressed the second error (C1202), but you asked more than that.
Warning C4554 is caused by a Microsoft compiler bug involving template parameters and the << operator. So, (1 << N) generates a warning. If N were an ordinary parameter, there would be no warning of course.
The very simple workaround is to use (1 << (N)) instead of (1 << N), and C4554 goes away!