I would like to use template to specify sizes in functions. Let me give you an example.
I can do this:
int sub (int a[2][2]) {
}
int main () {
int a[2][2];
sub(a);
}
I can do this:
template<int size2>
int sub (int a[][size2]) {
}
int main () {
int a[2][2];
sub(a);
}
But what I would like is this:
template<int size1, int size2>
int sub (int a[size1][size2]) {
}
int main () {
int a[2][2];
sub(a);
}
How could I?
The better option is probably to use std::array, if you have C++11 support, or std::vector, if not. If you really want to use C-style arrays, you can pass them by reference, using the following syntax.
template<size_t size1, size_t size2>
int sub (int (&a)[size1][size2]) {
// ...
}
int main() {
int a[2][2];
sub(a);
}
As Brian Bi already wrote, the best way to go is to use std::array.
But to answer your question, it is halfway possible to do what you want.
When you use a C-style 2D array as an argument to a function, it decays to a pointer to an array of the second dimension. For example int a[6][6] decays to int (*a)[6], so the first dimension is hidden and means nothing to the compiler. The second dimension however, can be used as template parameters and can be deduced.
For example:
template<int S>
void func(int (*a)[S])
{
cout << S << endl;
}
and then:
int a[66][67];
func(a);
prints "67".
Here is another way (sub<2,2>:
template<int size1, int size2>
int sub (int a[size1][size2]) {
}
void main(int argc, char **argv)
{
int a[2][2];
sub<2,2>(a);
}
Related
I need to copy from end to start an array of longs to an array of longs as is shown in the code bellow. Is there any function similar to memcpy for the required purpose ?
typedef long int myT;
const size_t n=5;
myT a[n];
myT b[n]={12,45,56,76,78};
int main(int argc, char **argv)
{
myT *p1=&a[0];
myT *p2=&b[n];
for(auto i=n;i-->0;)
*p1++=*--p2;
return 0;
}
That's what std::reverse_copy does.
int main()
{
std::reverse_copy(b, b+n, a);
}
or since C++11:
int main()
{
std::reverse_copy(std::begin(b), std::end(b), std::begin(a));
}
I am new to c++ and have a couple questions regarding passing arrays by reference to functions (so that the arrays are modified by the function). I realize there are similar questions that have been asked already, but there are a few points that I think were not covered in those previous questions (at least from what I saw). From what I have gathered so far, one can pass an array by reference by doing the following:
#include<iostream>
using namespace std;
void modify_array(int* a);
int main()
{
int array[10];
modify_array(&array[0]);
for(int i=0;i<10;i++)
{
cout<<array[i]<<endl;
}
}
void modify_array(int* a)
{
int i;
for(i=0;i<10;i++)
{
*(a+i)=i;
}
}
This makes sense to me but if I change the function to:
void modify_array(int* a)
{
int i;
for(i=0;i<10;i++)
{
a[i]=i; //line changed
}
}
This also works. Is there a difference? Or is the second just a short cut? Also in the case of passing 2d arrays I would have guessed that the following code would work:
#include<iostream>
using namespace std;
void modify_array(int* a);
int main()
{
int array[10][10];
modify_array(&array[0][0]);
}
void modify_array(int* a)
{
int i,j;
for(i=0;i<10;i++)
{
for(j=0;j<10;j++)
{
a[i][j]=i*j;
}
}
}
But this doesn't. From what I have seen in other related questions, you would do something like:
void modify_array(int (*a)[10])
{
int i,j;
//a[i][j]= blah blah blah;
}
or,
void modify_array(int (&a)[10][10])
{
int i,j;
//a[i][j]= blah blah blah;
}
What is the difference between these latter two function definitions? What do experienced c++ programmers recommend using: the (*a)[10][10] notation or the (&a)[10][10] notation?
Writing *(a+i)=i; or a[i]=i; are equivalent. The first is seen as an offset applied to the pointer to the array and assigning the value to the pointee, while the second is assigning the value to the element of the array.
However, when passing a pointer to a function modify_array(int* a), it cannot deduce that the pointee is a 2D array, and does not know what size to offset to address the other lines of the array, with a[i][j]=i*j;. For the compiler, it can only access the first dimension of the array.
The proper way to do what you need is this
#include<iostream>
using namespace std;
void modify_array(int (&a)[10][10]);
int main()
{
int array[10][10];
modify_array(array);
for(int i=0;i<10;i++)
{
for(int j=0;j<10;j++)
{
cout<<array[i][j]<<endl;
}
}
}
void modify_array(int (&a)[10][10])
{
int i;
for(i=0;i<10;i++)
{
for(int j=0;j<10;j++)
{
a[i][j]=i*j;
}
}
}
Live example
The function is expecting an int array of 10x10, passed by reference.
I've just tried:
class Test
{
public:
int iArray[][];
}
...is this not possible? Do I have to set a constant value?
like:
class Test
{
public:
const int iArray[5][4];
}
I want to define [x][y] later, just have the placements there. Else it wouldn't be "dynamic" and I don't want to use a vector because I want to be able to access the values by "X" and "Y".
I think better way to achieve this is to use pointers. You can do like this.
#include <cstdlib>
#include <iostream>
using namespace std;
class PointerTest {
private:
int** array;
int x, y;
public :
void setValue(int row, int col,int value);
int getValue(int row, int col);
PointerTest(int row, int col);
~PointerTest() {
for(int i=0;i<x;i++) {
delete array[y];
}
}
};
PointerTest::PointerTest(int row, int col) {
x=row, y=col;
for(int i=0;i<row;i++) {
*array=new int[col];
}
}
void PointerTest::setValue(int row, int col, int value) {
*(array[row])=value;
}
int PointerTest::getValue(int row, int col) {
return *(array[row]);
}
int main(int argc, char *argv[])
{
PointerTest* t=new PointerTest(4,5);
t->setValue(0,0,464);
cout<<"The value in array: "<<t->getValue(0,0)<<endl;
system("PAUSE");
return EXIT_SUCCESS;
}
What about
tempalte <int N1, int N2> class Test
{
public:
int iArray[N1][N2];
};
?
What about putting a std::vector in a vector?
std::vector< std::vector< const int > > iArray;
There aren't many reason to use "plain" arrays in C++.
If you want to decide int iArray[][]; size later then you can use vector< vector<int> > iArray;.
The other way is to use nested new[], which would be little complex.
No this is not possible. But you can have a pointer in your class like
int **ptr;
and then in the constructor or where ever allocate the memory for your array with
ptr = (int **)malloc( the size you want );
or with the "new[]"-operator in C++.
but if you are using C++ .. the best way is to use:
std::vector< std::vector< int >> array;
class Test
{
public:
Test()
{
iArray = new int*[5];
for(int i = 0; i < 5; i++)
iArray[i] = new int[4];
}
~Test()
{
for(int i = 0; i < 5; i++)
delete[] iArray[i];
delete[] iArray;
}
int** iArray;
};
Will allow you to allocate a 2d int array at runtime (in this example it is a 5x4), but in all honestly I would use vectors as pointed out by some other posters, you don't need to worry about freeing the memory afterwards like you do with the use of new.
I'm trying to use pointers of arrays to use as arguments for a function which generates an array.
void generateArray(int *a[], int *si){
srand(time(0));
for (int j=0;j<*si;j++)
*a[j]=(0+rand()%9);
} //end generateArray;
int main() {
const int size=5;
int a[size];
generateArray(&a, &size);
return 0;
} //end main
But when I compile this this message appears:
cannot convert `int (*)[5]' to `int**' for argument `1' to `void generateArray(int**, int*)'
You're over-complicating it - it just needs to be:
void generateArray(int *a, int si)
{
for (int j = 0; j < si; j++)
a[j] = rand() % 9;
}
int main()
{
const int size=5;
int a[size];
generateArray(a, size);
return 0;
}
When you pass an array as a parameter to a function it decays to a pointer to the first element of the array. So there is normally never a need to pass a pointer to an array.
int *a[], when used as a function parameter (but not in normal declarations), is a pointer to a pointer, not a pointer to an array (in normal declarations, it is an array of pointers). A pointer to an array looks like this:
int (*aptr)[N]
Where N is a particular positive integer (not a variable).
If you make your function a template, you can do it and you don't even need to pass the size of the array (because it is automatically deduced):
template<size_t SZ>
void generateArray(int (*aptr)[SZ])
{
for (size_t i=0; i<SZ; ++i)
(*aptr)[i] = rand() % 9;
}
int main()
{
int a[5];
generateArray(&a);
}
You could also take a reference:
template<size_t SZ>
void generateArray(int (&arr)[SZ])
{
for (size_t i=0; i<SZ; ++i)
arr[i] = rand() % 9;
}
int main()
{
int a[5];
generateArray(a);
}
You do not need to take a pointer to the array in order to pass it to an array-generating function, because arrays already decay to pointers when you pass them to functions. Simply make the parameter int a[], and use it as a regular array inside the function, the changes will be made to the array that you have passed in.
void generateArray(int a[], int si) {
srand(time(0));
for (int j=0;j<*si;j++)
a[j]=(0+rand()%9);
}
int main(){
const int size=5;
int a[size];
generateArray(a, size);
return 0;
}
As a side note, you do not need to pass the size by pointer, because you are not changing it inside the function. Moreover, it is not a good idea to pass a pointer to constant to a parameter that expects a pointer to non-constant.
I'm guessing this will help.
When passed as functions arguments, arrays act the same way as pointers. So you don't need to reference them. Simply type:
int x[]
or
int x[a]
. Both ways will work. I guess its the same thing Konrad Rudolf was saying, figured as much.
This is another method . Passing array as a pointer to the function
void generateArray(int *array, int size) {
srand(time(0));
for (int j=0;j<size;j++)
array[j]=(0+rand()%9);
}
int main(){
const int size=5;
int a[size];
generateArray(a, size);
return 0;
}
The structure is defined as
struct state{
string node_name;
int node_no;
int node_val;
int occupant;
vector<int>node_con;
};
state s[100][100]
I want to send it to a function along with i and j values , where s[i][j] , (i->rows , j-> columns) . How will the struct be sent with both i and j ?
This way
void f(StructName (*a)[100], int i, int j) {
}
Please read about two dimensional arrays and pointer to arrays. Alternatively in C++ you can pass it by a reference, which will make it not decay to its first element
void f(StructName (&a)[100][100], int i, int j) {
}
in C there is no way (AFAIK)
in C++ you could do this
template <class T, int N, int M>
void f(T (&a)[N][M])
{
//...
}
Alternatively, you could pass the dimensions manually, or hard-code them
In C, you can wrap it up in another structure :-)
I see stuff that doesn't look like C in your code ...
struct state {
string node_name;
int node_no;
int node_val;
int occupant;
vector<int>node_con;
};
struct wrap {
int i;
int j;
struct state (*ps)[];
};
int main(void) {
struct state s[100][100];
struct wrap x;
x.i = 100;
x.j = 100;
x.ps = s;
fx(x);
return 0;
}
You mean passing an array of structures. I think it should be this:
struct state{
string node_name;
int node_no;
int node_val;
int occupant;
vector<int>node_con;
};
state s[100][100];
void doSomething(state theState[][100], int i, int j)
{
cout << theState[i][j].node_name << endl;
}
int main()
{
s[0][1].node_name = "s[0][1]";
doSomething(s, 0, 1);
}