Map function in C++ with templates - c++

I'm trying to learn templates in C++ and one of the things I was trying was to code a map function like the ones you typically find in functional languages. The idea was something like this:
template <class X> X * myMap(X * func(X), X * array, int size)
{
X * temp;
for(int i = 0, i < size, i++) {temp[i] = (*func)(array[i]);}
return temp;
}
But when I try to use this in:
int test(int k) { return 2 * k;}
int main(void)
{
int k[5] = {1,2,3,4,5};
int *q = new int[5];
q = myMap(&test, k, 5);
for(int i=0; i<5; i++) {cout << q[i];}
delete [] q;
return 0;
}
I got a type mismatch error when compiling:
main.cpp:25: error: no matching function for call to ‘myMap(int (*)(int), int [5], int)’
I tried to change it to:
int main(void)
{
int *k = new int[5];
int *q = new int[5];
for(int i=0; i<5;i++) {k[i] = i;}
q = myMap(&test, k, 5);
for(int i=0; i<5; i++) {cout << q[i];}
delete [] q;
return 0;
}
The error message changes to:
main.cpp:26: error: no matching function for call to ‘myMap(int (*)(int), int*&, int)’
This is probably something very wrong, but I can't find where.
EDIT: The errors where:
1) I mistyped the pointer to function. It's X (*func)(X) instead of X * func(X) .
2) forgot to allocate temp. Must do X * temp = new X[size].
3) are there any more errors?

X * func(X) does not say what you think it says. You want X (*func)(X).

You're just getting the syntax for a function pointer wrong here. You want to say:
template <class X>
X* myMap(X (* func)(X), X * array, int size)
{
...
}
To make this function more generic, use a template parameter instead of a function pointer so you can use both plain function pointers and C++ function objects (functors).
template <class X, class F>
X* myMap(F func, X * array, int size)
{
...
}

You were very close. Just missing parens around X(*func)(X). Couple other syntax errors, fixed here:
#include <iostream>
using namespace std;
template <class X> X * myMap(X(*func)(X), X * array, int size)
{
X * temp;
for(int i = 0; i < size; i++) {temp[i] = (*func)(array[i]);}
return temp;
}
int test(int k) { return 2 * k;}
int main(void)
{
int k[5] = {1,2,3,4,5};
int *q = new int[5];
q = myMap(&test, k, 5);
for(int i=0; i<5; i++) {cout << q[i];}
delete [] q;
return 0;
}

You're not calling your templated MyMap function, you'reattempting to call a non-templated MyMap function. Try q= MyMap(.....)

Related

A Function returning an array from 1 int input

I made a function the returns an array like so
void array_function(int i){
int* a = NULL;
a = new int[3];
a = {i-1, i, i+1};
return a;
}
Now I want to call this function in the a new function
int main(){
int n = 3
for(int i = 0; i < n; i++){
//call the function
}
}
I am not sure how I can call the function to give me the array, any help will be appreciated
Use std::array instead. It has more friendly value semantics:
#include <array>
std::array<int, 3> array_function(int const i) {
return {{ i - 1, i, i + 1 }};
}
int main() {
for(int i = 0; i < 3; i++){
auto arr = array_function(i);
// Use array
}
}
First your function is void, which translates as no-return-function. Make it return int* like
int* array_function(int i)
Now, to call the function you need to assign it to a temporary variable, which you can do work and then you should delete it. Full code:
int* array_function(int i){
int* a = new int[3];
a[0] = i-1, a[1] = i, a[2] = i+1;
return a;
}
int main(){
int n = 3;
for(int i = 0; i < n; i++){
int* a = array_function(i); // if you are going to do something with this array, which you will
// some work with a
delete[] a; // delete it to release memory from heap, everytime you do new, you should use delete at the end of your program
}
}
You want something like this to create the array, since the method in your question does not have a return type assigned (void means that it returns nothing), you have to define a return type for the method to work, in this case a pointer to an array:
int* array_function(int i){
int* a = NULL;
a = new int[3];
a = {i-1, i, i+1};
return a;
}
And then just store the result of the method in a local variable like this:
int* myArray = array_function(n);

Reverse Pointer function issue

I'm having an issue with the pointer return function. The error, "calling object type 'int* ' is not a function or a function pointer" reverseArray = reverseArray(array,size);.I am not sure why it's giving me this error, this is not my solution I'm using this solution as a guidance to help me solve the problem. Since I've sat for now 2 hours trying to solve it and I got no where with it, so I decide to look it up and get an idea on how to approach the problem. And break down their solution by using a debugger to see why their solution works. I know it's a bad thing to do because I'm not learning how to solve problems on my own.
#include <iostream>
int* reverseArray(int [], int );
int main()
{ const int size =5;
int array[size] = {1,2,3,4,5};
int* reverseArray;
for(int i =0; i < size;i++)
{
std::cout << array[i];
}
reverseArray = reverseArray(array,size);
for(int i =0; i <size;i++)
{
std::cout <<array[i];
}
return 0;
}
int* reverseArray(int array [],int size)
{
int* newArray;
newArray = new int[size];
int j = 0;
for(int k =size-1;k>=0;k--)
{
newArray[j] = array[k];
j++;
}
return newArray;
}
The error is self explanatory.
"calling object type 'int* ' is not a function or a function pointer". In you main() function, you named the array you want to pass as a parameter to your reverseArray() function with the same name as your function (reverseArray). The compiler get confused within that scope, because of this and thinks you're calling a variable as a function.
See below:
#include <iostream>
int* reverseArray(int [], int );
int main()
{ const int size =5;
int array[size] = {1,2,3,4,5};
int* reverseArray; // Change this name to something else
for(int i =0; i < size;i++)
{
std::cout << array[i];
}
reverseArray = reverseArray(array,size);
for(int i =0; i <size;i++)
{
std::cout <<array[i];
}
return 0;
}
Hope it helps :)

C++ qsort 2D array

I am still getting lldb error, because i am probably accessing memory, that i shouldn't.
It looks like i am doing something wrong when manipulating with parameters in io_seg_sort, because before calling qsort, it is still ok.
#define IO_SEG_IMAX (IO_SEG - 1)
static int io_seg_sort (const void * seg1, const void * seg2) {
int * _seg1 = (int *)seg1;
int * _seg2 = (int *)seg2;
cout << _seg1[1] <<endl; // this gives some random values and not what i am expecting
if (_seg1[1] > _seg2[1]) {
return 1;
}
else if (_seg1[1] < _seg2[1]) {
return -1;
}
else {
return 0;
}
}
int **temp = new int *[IO_SEG];
for (int i = 0; i <= IO_SEG_IMAX; i++) {
temp[i] = new int[2];
memcpy(temp[i], inputs[i], sizeof(int) * 2);
}
qsort(temp, IO_SEG, sizeof(int *) , io_seg_sort);
EDIT1: the problem is i am getting some random values in io_seg_sort when calling cout instead of what i am expecting. inputs[i] is class member int inputs[IO_SEG][2];
You're putting IO_SEG_MAX + 1 items into an array that's IO_SEG long.
for (int i = 0; i <= IO_SEG_IMAX; i++) {
temp[i] = new int[2];
memcpy(temp[i], inputs[i], sizeof(int) * 2);
}
That should be:
for (int i = 0; i < IO_SEG; i++) {
temp[i] = new int[2];
memcpy(temp[i], inputs[i], sizeof(int) * 2);
}
But if you really intend to do this in C++, you should look into std::vector and std::sort.
The primary reason your code prints garbage is that you have mismatched levels of indirection inside the comparison function. Your temp array that you pass to qsort consists of pointers to two-element arrays. That means that inside the comparison function you actually receive pointers to pointers to int. I.e. this is already incorrect
static int io_seg_sort (const void * seg1, const void * seg2) {
int * _seg1 = (int *)seg1;
int * _seg2 = (int *)seg2;
cout << _seg1[1] <<endl;
You have to do something like
static int io_seg_sort (const void * seg1, const void * seg2) {
const int * _seg1 = *(const int *const *) seg1;
const int * _seg2 = *(const int *const *) seg2;
to get access to your arrays through _seg1 and _seg2 as you do it in the body of io_seg_sort (I also added some const qualifiers, although they are not required for the code to work.)

C++: Segamentation fault when reading array in function passed as argument

I get a segmentation fault when reading the second element of h array inside the g function. Strangely, when debugging can I actually watch the array content. I think that besides this curious thing that shows that the data is there, I have done something wrong. Thanks in advance.
#include <iostream>
using namespace std;
void function(void function_passed(double* [], int), int n);
void g(double* [] ,int n_g);
int main()
{
function(g,5);
return 0;
}
void g(double* h[], int n_g)
{
for (int i = 0; i < n_g; i++)
cout << i << " "<< *h[i] << endl;
}
void function(void function_passed(double* [], int ), int n)
{
double * h = new double[n];
for (int i=0;i<n;i++)
h[i] = i + 10;
function_passed(&h,n);
delete[] h;
}
void func(void g(double* [],int n ), int n)
{
double * h = new double[n];
for (int i=0;i<n;i++)
h[i] = i;
g(&h,n);
delete[] h;
}
Operator precedence has bitten you. Inside g:
*h[i] is parsed as *(h[i]) but what you want is (*h)[i].
*h[i] is okay for the first iteration, but in the second one (and all subsequent) you're dereferencing an invalid pointer h+i.
On the second thought, you're actually invoking undefined behavior - pointer arithmetic is valid only between pointers that point to the same array.

Converting multidimensional arrays to pointers in c++

I have a program that looks like the following:
double[4][4] startMatrix;
double[4][4] inverseMatrix;
initialize(startMatrix) //this puts the information I want in startMatrix
I now want to calculate the inverse of startMatrix and put it into inverseMatrix. I have a library function for this purpose whose prototype is the following:
void MatrixInversion(double** A, int order, double** B)
that takes the inverse of A and puts it in B. The problem is that I need to know how to convert the double[4][4] into a double** to give to the function. I've tried just doing it the "obvious way":
MatrixInversion((double**)startMatrix, 4, (double**)inverseMatrix))
but that doesn't seem to work. Is that actually the right way to do it?
No, there's no right way to do specifically that. A double[4][4] array is not convertible to a double ** pointer. These are two alternative, incompatible ways to implement a 2D array. Something needs to be changed: either the function's interface, or the structure of the array passed as an argument.
The simplest way to do the latter, i.e. to make your existing double[4][4] array compatible with the function, is to create temporary "index" arrays of type double *[4] pointing to the beginnings of each row in each matrix
double *startRows[4] = { startMatrix[0], startMatrix[1], startMatrix[2] , startMatrix[3] };
double *inverseRows[4] = { /* same thing here */ };
and pass these "index" arrays instead
MatrixInversion(startRows, 4, inverseRows);
Once the function finished working, you can forget about the startRows and inverseRows arrays, since the result will be placed into your original inverseMatrix array correctly.
For given reason that two-dimensional array (one contiguous block of memory) and an array of pointers (not contiguous) are very different things, you can't pass a two-dimensional array to a function working with pointer-to-pointer.
One thing you could do: templates. Make the size of the second dimension a template parameter.
#include <iostream>
template <unsigned N>
void print(double a[][N], unsigned order)
{
for (unsigned y = 0; y < order; ++y) {
for (unsigned x = 0; x < N; ++x) {
std::cout << a[y][x] << ' ';
}
std::cout << '\n';
}
}
int main()
{
double arr[3][3] = {{1, 2.3, 4}, {2.5, 5, -1.0}, {0, 1.1, 0}};
print(arr, 3);
}
Another, a bit clumsier way might be to make the function accept a pointer to a single-dimensional array, and both width and height given as arguments, and calculate the indexes into a two-dimensional representation yourself.
#include <iostream>
void print(double *a, unsigned height, unsigned width)
{
for (unsigned y = 0; y < height; ++y) {
for (unsigned x = 0; x < width; ++x) {
std::cout << a[y * width + x] << ' ';
}
std::cout << '\n';
}
}
int main()
{
double arr[3][3] = {{1, 2.3, 4}, {2.5, 5, -1.0}, {0, 1.1, 0}};
print(&arr[0][0], 3, 3);
}
Naturally, a matrix is something that deserves a class of its own (but the above might still be relevant, if you need to write helper functions).
Since you are using C++, the proper way to do something like this would be with a custom class and some templates. The following example is rather rough, but it gets the basic point across.
#include <iostream>
using namespace std;
template <int matrix_size>
class SquareMatrix
{
public:
int size(void) { return matrix_size; }
double array[matrix_size][matrix_size];
void copyInverse(const SquareMatrix<matrix_size> & src);
void print(void);
};
template <int matrix_size>
void SquareMatrix<matrix_size>::copyInverse(const SquareMatrix<matrix_size> & src)
{
int inv_x;
int inv_y;
for (int x = 0; x < matrix_size; x++)
{
inv_x = matrix_size - 1 - x;
for (int y = 0; y < matrix_size; y++)
{
inv_y = matrix_size - 1 - y;
array[x][y] = src.array[inv_x][inv_y];
}
}
}
template <int matrix_size>
void SquareMatrix<matrix_size>::print(void)
{
for (int y = 0; y < 4; y++)
{
for (int x = 0; x < 4; x++)
{
cout << array[x][y] << " ";
}
cout << endl;
}
}
template <int matrix_size>
void Initialize(SquareMatrix<matrix_size> & matrix);
int main(int argc, char * argList[])
{
SquareMatrix<4> startMatrix;
SquareMatrix<4> inverseMatrix;
Initialize(startMatrix);
inverseMatrix.copyInverse(startMatrix);
cout << "Start:" << endl;
startMatrix.print();
cout << "Inverse:" << endl;
inverseMatrix.print();
return 0;
}
template <int matrix_size>
void Initialize(SquareMatrix<matrix_size> & matrix)
{
for (int x = 0; x < matrix_size; x++)
{
for (int y = 0; y < matrix_size; y++)
{
matrix.array[x][y] = (x+1)*10+(y+1);
}
}
}
Two dimensional array is not a pointer to pointer or something similar. The correct type for you startMatrix is double (*)[4]. For your function, the signature should be like:
MatrixInversion( double (*A)[4], int order, double (*B)[4] );
There is a solution using the pointer to point by bobobobo
William Sherif (bobobobo) used the C version and I just want to show C++ version of bobobobo's answer.
int numRows = 16 ;
int numCols = 5 ;
int **a ;
a = new int*[ numRows* sizeof(int*) ];
for( int row = 0 ; row < numRows ; row++ )
{
a[row] = new int[ numCols*sizeof(int) ];
}
The rest of code is the same with bobobobo's.
You can definitely do something like the code below, if you want.
template <typename T, int n>
class MatrixP
{
public:
MatrixP operator()(T array[][n])
{
for (auto i = 0; i < n; ++i) {
v_[i] = &array[i][0];
}
return *this;
}
operator T**()
{
return v_;
}
private:
T* v_[n] = {};
};
void foo(int** pp, int m, int n)
{
for (auto i = 0; i < m; ++i) {
for (auto j = 0; j < n; ++j) {
std::cout << pp[i][j] << std::endl;
}
}
}
int main(int argc, char** argv)
{
int array[2][2] = { { 1, 2 }, { 3, 4 } };
auto pa = MatrixP<int, 2>()(array);
foo(pa, 2, 2);
}
The problem is that a two-dimensional array is not the same as an array of pointers. A two-dimensional array stores the elements one row after another — so, when you pass such an array around, only a pointer to the start is given. The receiving function can work out how to find any element of the array, but only if it knows the length of each row.
So, your receiving function should be declared as void MatrixInversion(double A[4][], int order, double B[4][]).
by nice coding if c++:
struct matrix {
double m[4][4];
};
matrix startMatrix;
matrix inverseMatrix;
so the interface would be
void MatrixInversion(matrix &A, int order, matrix &B);
and use it
MatrixInversion(startMatrix, 4, inverseMatrix);
The benefit
the interface is very simple and clear.
once need to modify "m" of matrix internally, you don't need to update the interface.
Or this way
struct matrix {
void Inversion(matrix &inv, int order) {...}
protected:
double m[4][4];
};
matrix startMatrix;
matrix inverseMatrix;
...
An ugly way in c
void MatrixInversion(void *A, int order, void *B);
MatrixInversion((void*)startMatrix, 4, (void*)inverseMatrix);
EDIT: reference code for MatrixInversion which will not crash:
void MatrixInversion(void *A, int order, void *B)
{
double _a[4][4];
double _b[4][4];
memcpy(_a, A, sizeof _a);
memcpy(_b, B, sizeof _b);
// processing data here
// copy back after done
memcpy(B, _b, sizeof _b);
}