Make the compiler deduce the parameter of a function before compilation - c++

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.

Related

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.

'Constant Expression Required' Error while keeping formal argument as a constant

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

Passing array by reference - subset of a larger array

I know there are other ways of implementing this or using containers. This is just to satisfy my curiosity. Suppose I have the following code:
void byref(int (&a)[5]);
int main()
{
int a[5];
byref(a);
}
An advantage of passing a C-style array by reference is that sizeof will work on it, as will std::end. But now it is only possible to pass an array of exactly this size.
Is it possible to pass a subset of a larger array to this function by reference? For example, I'd like to do:
int main()
{
int a[10];
byref(a + 1);
}
Is there any way to make this work?
I got it to build and run, giving expected values in VS2015, but of course the code looks very dodgy:
byref(reinterpret_cast<int(&)[5]>(*(a + 1)));
I have only an idea of wrapping the bad looking cast into a function:
#include <iostream>
#include <cassert>
void byref(int (&a)[5])
{
std::cout << "Hello!" << std::endl;
}
template <size_t M, class T, size_t N>
T (&subarray(T (&a)[N], size_t start))[M]
{
assert(start < N && start + M <= N);
return reinterpret_cast<T(&)[M]>(a[start]);
}
int main()
{
int a[5], b[8];
byref(a);
byref(subarray<5>(subarray<6>(b, 0), 1));
}
With this prototype, I fail to see another way to proceed than casting.
Typically, I see this one too: byref((int(&)[5])*(b + 5));, but of course it's the same and less safe than yours.
So, I don't see any clear and pretty way to do it (except for a macro maybe). I will upvote your question however, in order to see if you are missing something here!

[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

Defining Exponential Preprocessor Macro

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;