Defining Exponential Preprocessor Macro - c++

I'm planning on competing in a programming competition in a few months, and I want to define some macros to minimize the typing i need to do. Raising a number to a power is common enough to benefit from this I've been told. I only need it to work with integer arguments (though the arguments themselves may be expressions). I've tried a few different variations but I can't get the correct syntax.
/* c is where the result is stored */
#define EXP(a,b,c) c=a; for (int ii=0; ii<(b)-1; c*=(a), ii++);
This works but i can't use EXP(a,b,c) in an expression like function( EXP(a,b,c) ); I'd have to do
int result;
EXP(a,b,result);
function(result);
This, I think would work inside expressions but it fails to compile
#define EXP(a,b) int c=a; for (int ii=0; ii<(b)-1; (c)*=(a), i++); c
with: error: expected primary-expression before ‘int’ when used in:
int result = EXP(2,10);
this is my representative function:
int EXP(int base, int power) {
int result = base;
for (int ii=0; ii<power-1; ii++)
result *= base;
return result;
}

Using a macro function is the wrong tool for the job. Nevertheless, you say you think it would work inside expressions, consider how would that look for the actual compiler once the preprocessor did his work:
int result = int c=2; for (int ii=0; ii<(10)-1; (c)*=(2), i++); c
No matter how hard you try, you can't do variable definitions nor for loops within an expression.

You could use a recursive template template approach:
template<int base, unsigned int exp>
struct Pow {
enum { value = base * power<base, exp-1>::value };
};
// stopping condition
template<int base>
struct Pow<base,0> {
enum { value = 1 };
};
and use it like this:
int i = Pow<10,2>::value;

Related

Make the compiler deduce the parameter of a function before compilation

Here is an example of my problem.
#include <stdio.h>
//template<std::size_t A> <-- Tried to solve the problem by using template
void func1(const int power){
const int length = 1 << power;
int twoDArrayA[length][length];
for (int j = 0; j < power; j++)
{
/* Code */
}
}
int main() {
func1(4);
func1(3);
func1(2);
}
I wonder if I could somehow allow the compiler to deduce parameter power in func1 before it compiles. So instead of compiles one function, it compiles 4 functions in the format of func1 with different power value.
The reason for this is because I would like to use Vitis HLS to unroll the loop and partition the matrix so that it could be implemented onto a FPGA, where a variable-length loop or array cannot work properly.
You can do this with a template, but you've got the wrong syntax. It should be:
template<std::size_t power>
void func1(){
const std::size_t length = 1 << power;
int twoDArrayA[length][length];
...
}
int main() {
func1<4>();
...
}
Note that your variable length array (VLA) is legal C++ if length is a compile-time constant (as it is here). Nevertheless, std::array would be a better bet.
PS: Thanks for telling us why you want to do this. That was a nice touch.

Is there a way to fix this error : no match for 'operator[]' (operand types are 'empl' and 'int')

Im getting homework done but i faced this problem i tried everything changing variables name, changing function ....
I looked into this problem on google still no idea how to fix this error.
#include<stdio.h>
#include<iostream>
struct empl {
char nom;
char pre;
float salaire;
double cin;
}empl;
struct empl t[50];
struct empl E;
int taille(int n)
{
printf("saisie la taille de tableaux\n");
scanf("%d\n", &n);
return 0;
}
int remplire(int n, struct empl t, int i)
{
for (i = 1; i <= n; i++)
{
printf("t[%d].nom= ", i);
scanf("%s\n", &t[i].nom);
printf("t[%d].prenom= ", i);
scanf("%s\n", &t[i].pre);
printf("t[%d].salaire= ", i);
scanf("%f\n", &t[i].salaire);
printf("t[%d].CIN= ", i);
scanf("%lf\n", &t[i].cin);
}
}
int main()
{
int i, n;
int taille(int n),
taille(n);
int remplire(int n, struct empl t, int i);
remplire(n, t, i);
}
Although your code is written mostly in C style, you seem to be compiling it with a C++ compiler, as it accepts #include <iostream> (though you do not appear to use anything from it), and it has a notion of operator overloading. C and C++ are distinct languages, and the distinction is somewhat relevant here.
In either language, however, the code you have presented is flawed. The problem is with the several expressions in function remplire that follow this pattern: &t[i].nom. Absent any operator overloading (which is not available in C anyway), the [] operator in those expressions requires one of its operands to designate either a pointer or an array, and the other to designate an integer. Although there is a file-scope variable t that is an array, inside remplire() that is shadowed by a function parameter with the same name. Inside that function, then, t refers the the parameter, which is a struct empl, not an array or pointer (or integer).
Your compiler ought to be giving you another clue, too, where you call that function ...
remplire(n,t,i);
..., passing the global t as an argument. The compiler very much should complain about a type mismatch between the second argument (t) and the corresponding function parameter.
Perhaps what you wanted to do is simply to declare remplire() to accept a structure pointer as its second parameter:
int remplire(int n, struct empl *t, int i)
While you're at it, do remove the redundant local declaration of that function inside main(). You don't need that as long as remplire() is defined before main(), and if you want to have a separate declaration of that function then it would best be placed at file scope, and probably in a header file.
First of all iostream is C++ header coming from standard library and will not work for C program. And now issues:
int taille (int n)
{
printf("saisie la taille de tableaux\n");
scanf("%d\n",&n);
return 0;
}
This function is called with an input parameter - that means you can pass a value into a function, but not access the parameter and hope it will be used in other places. To correct this you should declare the function should look like this:
int taille (int * n)
{
printf("saisie la taille de tableaux\n");
scanf("%d\n", n);
return 0;
}
Next function - similar problem, it should look like this:
int remplire (int n , struct empl * t ,int i)
{
for (i=1;i<=n;i++)
{
printf("t[%d].nom= ",i);
scanf("%s\n",&t[i].nom);
printf("t[%d].prenom= ",i);
scanf("%s\n",&t[i].pre);
printf("t[%d].salaire= ",i);
scanf("%f\n",&t[i].salaire);
printf("t[%d].CIN= ",i);
scanf("%lf\n",&t[i].cin);
}
}
Or even like this:
int remplire (int n , int i)
as t is global variable. Also this function should return some value as it is declared to return int.
And now the main function:
int main()
{
int i,n;
int taille(int n),
taille(n);
int remplire(int n,struct empl t,int i);
remplire(n,t,i);
}
Don't redeclare functions inside another function, even if it is permissible it does not mean you should do it. Also main function should return 0 if everything works fine. To correct the function write it like this:
int main()
{
int i,n;
taille(& n);
remplire(n,& t,i);
}
Some good advice, please read some books to learn how to program in C if you want to go that way.
There are many issues in your code.
Starting reading a good C textbook is advised.
You probably want this:
#include <stdio.h>
#include <iostream>
struct empl {
char nom[30];
char pre[30];
float salaire;
double cin;
}empl;
struct empl t[50];
struct empl E;
int taille(int & n)
{
printf("saisie la taille de tableaux\n");
scanf("%d", &n);
return 0;
}
void remplire(int n, struct empl *t)
{
for (int i = 0; i < n; i++)
{
printf("t[%d].nom= ", i);
scanf("%s", &t[i].nom);
printf("t[%d].prenom= ", i);
scanf("%s", &t[i].pre);
printf("t[%d].salaire= ", i);
scanf("%f", &t[i].salaire);
printf("t[%d].CIN= ", i);
scanf("%lf", &t[i].cin);
}
}
int main()
{
int n;
taille(n);
remplire(n, t);
}
It's still poor code and it's written mostly in C style, but it compiles and works as intended.
In C++ you'd do this totally differently.
You've declared this global array variable t
struct empl t[50];
and also declared a parameter t in this function
int remplire (int n , struct empl t ,int i)
Inside the function it's going to treat any instance of t as to be the parameter as that is nearer in scope than the global variable. So when you have code like this...
scanf("%s\n",&t[i].nom);
...it's going to throw up errors because t isn't an array.
The solution is to use variable names that have meaning like "employee_array" rather than single letters.
Also that call to scanf is wrong as for strings you don't need to pass in a pointer to the variable, so it should look like
scanf("%s\n",t[i].nom);
But you'd also need to make nom be a string too - currently it's only a char.

How to make a template with customized bit shift values

Suppose that I need a function template that does different amounts of bit shifts on different integer types. For example, if the input value n is of type char, the function does some calculations on n>>2 and n<<3. If it is short int, then the function uses n>>1 and n<<8. For int type, there would be n>>11 and n<<9, and so on. Of course, the values mentioned are just for example and there is no correlation between them and the size of int_type.
My suggestion for this problem was something like this:
template <typename Num_Type = char, int s1 = 2, int s2 = 3> void test1(Num_Type &n)
{
// this is just an example code:
int a = n >> s1,
b = n << s2;
// do some calculations on a and b
}
So I can use this template for different types of input value. But when I compile it, it gives me several warnings about undefined behavior in shift operations, because the value may be too big.
So the question can be asked in two forms:
How can I customize bit-shift operations without getting "undefined behavior" warnings? or
Can I have a limited data type, say intlength which can only have a specified range of numbers, say 0, 1, 2, ... , 31? I know it may sound stupid, but in this case, I can define the template as
template <typename Num_Type = char, intlength s1 = 2, intlength s2 = 3> void test1(Num_Type &n)
and so the compiler should not complain about shift values.
You can disable the warning for this function with a #pragma command, which depends on the compiler you are using. You will have to google that yourself.
Edit: since you mention you are using VisualStudio, here is a link to disable warnings. :)
Once you disable the warning you can add a static_assert to check if s1 and s2 are in range of the Num_Type. Although I find it strange that your compiler does not do that itself since everything is known at compile time.
template <typename Num_Type, int s1 = 2, int s2 = 3> void test1(Num_Type &n)
{
constexpr auto max = sizeof(Num_Type) * 8;
static_assert(s1 < max && s2 < max, "integer overflow");
// this is just an example code:
int a = n >> s1,
b = n << s2;
}
Live demo
The healthy way to change template function behavior depending on input type is to use template specialization. For example:
template <typename num_t> test(num_t n);
template <> test<int> (num_t n){
int shift_amount = 4;
// do shifts
}
template <> test<char> (num_t n){
int shift_amount = 1;
// do shifts
}
Also, make sure to surround your shifts with if checks to make sure there is no overflow.
I see no need for templates. All you need is simple overloading:
auto test(char n) { ... }
auto test(uint16_t n) { .. }
auto test(uint32_t n) { .. }

[C++ compile time assertions]: Can we throw a compilation error if some condition is not met?

I wrote a function:
template<int N> void tryHarder() {
for(int i = 0; i < N; i++) {
tryOnce();
}
}
but I only want it to compile if N is in between 0 and 10. Can I do it? How?
You can do it with static_assert declaration:
template<int N> void tryHarder() {
static_assert(N >= 0 && N <= 10, "N out of bounds!");
for(int i = 0; i < N; i++) {
tryOnce();
}
}
This feature is only avaliable since C++11. If you're stuck with C++03, take a look at Boost's static assert macro.
The whole idea of this are nice error messages. If you don't care for those, or can't even affor boost, you could do something as follows:
template<bool B>
struct assert_impl {
static const int value = 1;
};
template<>
struct assert_impl<false> {
static const int value = -1;
};
template<bool B>
struct assert {
// this will attempt to declare an array of negative
// size if template parameter evaluates to false
static char arr[assert_impl<B>::value];
};
template<int N>
void tryHarder()
{
assert< N <= 10 >();
}
int main()
{
tryHarder<5>(); // fine
tryHarder<15>(); // error, size of array is negative
}
For pre C++11 compilers, you could implement a template parameter constraint on the non-type parameter N.
For a description of how to do this, please see http://stroustrup.com/bs_faq2.html#constraints
Combined with the answers given so far already, the lower bound can be covered, too, by using unsigned int as template type. Negative values, if applied, will be converted to unsigned values high enough that they will be covered with the static_assert or the pre-C++11 solution anyway.
unsigned int additionally gives already semantically a hint that negative values shall not be applied to this template, which is why it (possibly) should be preferred in the specific case...
#if !defined(__cplusplus)
#error C++ compiler required.
#endif
This is just an example.
Here is the source link: http://msdn.microsoft.com/en-us/library/c8tk0xsk(v=vs.71).aspx
All i am saying is that you can use #error also
It is a directive
Edit #Pratik Chowdhruy: I agree with Paul R. This does not answer the question directly. Sorry to the community

How to invoke C++ function?

I have a function with the prototype as
void test( int array [] , int b);
I know we can replce the protoype as: void test(int*, int);
In main() we declare the following arrays :
int array1[10], array2[10];
To set the body of the function to 0,
test ( array1 , b)
{
for ( int i = 0 ; i < b ; i++)
array1[i] = 0;
}
can i do the follwing and why?
int main()
{// assuming b is the size of the array
test(array1 , b);
test(array2 , b) ;
return 0;
}
i know the basic of c++ im trying to write my own include files.
I am just wondering if this is possible and is it a good choise?
Not a direct answer to your question, but the fact that you talk about C++ and yet use plain old C arrays caught my attention:
Consider not using C arrays in the first place. Instead, use a std::vector<int>. This probably avoids the need to ask this question in the first place (and it avoids a whole lot of other issues). You don't need to bother about the right size type (int? size_t? Something else?) since std::vector gives you the right type already: std::vector<int>::size_type.
Your function signature would just be
void test( std::vector<int> &a );
The implementation for filling the vector with zeros would be:
void test( std::vector<int> &a )
{
std::fill( a.begin(), a.end(), 0 );
}
You may be asking about the difference between formal parameters and actual parameters.
In your prototype
void test(int *array, size_t size);
the names 'array' and 'size' are the formal parameters. You use those names inside the body of your function.
In the code that invokes the function, you can use different names, which are the actual parameters.
so
int main()
{
const size_t b = 10;
int array1[10], array2[10];
test(array1 , b);
test(array2 , b) ;
return 0;
}
Here array1 and b are the actual parameters to the first invocation and array2 and b are the actual parameters to the second invocation.
So yes, you can use whatever names you like as actual parameters, so long as the types of the variables match your prototype.
Yes, it's possible; but declaration in the function body should be same as what you declared as prototype:
void test (int array1[], int b) // <---- see here (prefer `unsigned int` for size)
{
for ( int i = 0 ; i < b ; i++)
array1[i] = 0;
}
It's better to use library function memset() if you want to set something to 0.
(As an advise, you can a build a library on top of what is already existing. Otherwise it will be like reinventing a wheel.)
Looks like you're migrating from C. Yes, this is possible, but you need to get the declarations right, or the compiler will throw an error.
The preferred C++ prototype would be
void test(int *array, size_t size);
In C++, you must declare the return type, and the type(s) of each argument in both the prototype and the implementation.
Note:
You don't need to use size_t, but it is preferred (even on C). size_t is included in stddef.h (and by extension cstddef which is the preferred C++ include). It is architecture dependent and is usually unsigned int in 32-bit systems and unsigned long long on 64-bit systems