Overwriting function parameter in a recursive function? - c++

So I have a class that has a protected pointer member of the following type
int *assigntoThis; // In the constructor I have initialized this to NULL.
I also have a public recursive member function of the same class with the following declaration
bool find(int* parent, std::string nameofnode, int* storeParentinThis);
The recursive function checks through child nodes and if the name of the child Node matches the string passed in as a parameter it will assign the address of parent to storeParentinThis.
This is how I call the function from another function of the same class.
bool find(root, "Thread", assigntoThis);
However, during runtime when I output the value stored in assigntoThis I get 00000000 = NULL. How do I change the value of assigntoThis inside my recursive function?

change to :
bool find(int* parent, std::string nameofnode, int*& storeParentinThis);
explanation:
here is a simplified version of your original code:
foo (int* p) { /// p bahaves as a local variable inside foo
p = 1;
}
int* p = 0;
foo(p);
// here p is still equal 0
this is actually similar to following code:
foo (int i) {
i = 1;
}
int i = 0;
foo(i);
// here i is still equal 0
which I think is easier to understand.
So if we want to return something from a function we must make a pointer to it or a reference to it, going backwards with examples:
foo (int* i) { // pointer example
*i = 1;
}
int i = 0;
foo(&i);
// here i is equal to 1
foo (int& i) { // using reference example
i = 1;
}
int i = 0;
foo(i);
// here i is equal to 1
Now it is easy to apply it to your case:
// pointer example
bool find(int* parent, std::string nameofnode, int** storeParentinThis) {
*storeParentinThis = parent;
}
// reference example
bool find(int* parent, std::string nameofnode, int*& storeParentinThis) {
storeParentinThis = parent;
}

Related

How to pass object array to a function?

class department
{
void max() ***HOW TO PASS ARRAY OF OBJECT HERE , WHAT PARAMETERS SHOULD I PASS***
{
}
};
class B : public department {
};
int main()
{
B a[10];
// a.max(a,n); ***HOW TO CALL THIS max FUNCTION***
return 0;
}
I want to pass the array of object a[10] to the max function. How do I call it and pass it?
I don't want to do it like this:
for(i = 0; i < n; i++)
{
a[i].max
}
You implemented max() as a non-static method of department, so you need a department object to call it on, like each B object in your array, eg:
for(int i = 0; i < 10; ++i)
{
a[i].max();
}
If this is not what you want, then max() needs to be taken out of department, or at least made to be static instead. Either way, you will have to change its input parameters to accept the array.
Try something more like this instead:
class department
{
public:
static void max(department *depts, int count)
{
//...
}
};
class B : public department {
};
int main()
{
B a[10];
department::max(a, 10);
return 0;
}
Online Demo
Alternatively:
class department {
};
class B : public department {
};
void max(department *depts, int count)
{
//...
}
int main()
{
B a[10];
max(a, 10);
return 0;
}
Online Demo
How to pass object array to a function?
The parameter of a function cannot be an array in C++. A parameter can be a reference to an array. Alternatively, it is common to pass iterator pointing to an element of an array. Object pointer is an iterator for an array.
department::max() is a non-static member function. It has empty parameter list, so it accepts no arguments at all, except for the implicit class instance that is used as the left hand operand of a member access operator. Since this function accepts no reference to array parameter nor a pointer parameter, there's no way to pass an array as an argument.
Here is an example of a function that does accept a reference to an array as a parameter, and of how to call such function:
void max(B (&arr)[10]);
int main()
{
B a[10];
max(a);
}

Difficulty in passing function pointer of a class member function

In trying to implement a suggested answer here in my own context, I am running into a compilation error.
Consider code:
#include <iostream>
class SIMPLE {
public:
SIMPLE() { for (int i = 0; i < 5; i++) val[i] = 5; };
int retval(int index) { return val[index]; }
private:
int val[5];
};
void print_array_of_length5(int (*fnptr)(int index)){
for (int i = 0; i < 5; i++)
printf("%d ", fnptr(i));
}
int global_array[5] = { 0, 1, 2, 3, 4 };
int global_function(int index){
return global_array[index];
}
int main(){
print_array_of_length5(&global_function);//Works fine.
int (SIMPLE::*p)(int) = &SIMPLE::retval;//Following method suggested in the answer above
class SIMPLE smpl;
print_array_of_length5(smpl.*p);//Compile error: a pointer to a bound function may only be used to call the function
}
The function works when supplied with the address of a global function. It does not work when passed smpl.*p analogous to the method suggested. How should one fix this error?
You need another overload for print_array_of_length5 in order to pass a member function pointer:
template<typename T>
void print_array_of_length5(int (T::*fnptr)(int index), T& obj)
{
for(int i = 0; i < 5; ++i)
{
printf("%d ", (obj.*fnptr)(i));
}
}
int main()
{
SIMPLE smpl;
print_array_of_length5(&SIMPLE::retval, smpl);
}
You can't pass a non-static member function pointer as a regular function pointer. Member functions have access to the this pointer, and the way they get that is via an invisible implicit function parameter. You need to have the object on which to call the function, and the function itself, be bound together, which a function pointer simply can't do.
What we can do is make print_array_of_length5 a function template, and allow it to take any type of callable. That would give you something like this:
template <typename Function>
void print_array_of_length5(Function func){
for (int i = 0; i < 5; i++)
printf("%d ", func(i));
}
To call it with a non-static member function, you can use a lambda expression, or std::bind(), like this:
SIMPLE smpl;
print_array_of_length5([&smpl](int foo){ return smpl.retval(foo); });
using namespace std::placeholders;
SIMPLE smpl;
auto func = std::bind(&SIMPLE::retval, &smpl, _1);
print_array_of_length5(func);

Returning a array from a void * argument in a function

I have a variadic function that takes at least 3 arguments, and is of the form
foo(void* ret_val, int mode, int num_params, ...)
The general use of the variadic function foo() can involve returning different data types as well as an arbitrary number of input arguments that can have various data types, but I am unable to find a way of returning an array.
How can I return an array?
The function definition is that the first argument returns an arbitrary type depending on the function invoked by foo(), mode is the mode of operation, and num_params is the number of additional input parameters, which can be zero. There is a switch statement inside foo() which depending on mode, can invoke one or more functions, and can return a value of an arbitrary type.
As a simplified example, suppose I have the following 3 functions that are invoked by foo():
void bar1(int i, int, j) {
// Do some calculations but return nothing.
}
int bar2() {
// Do some calculations and return a value.
}
int* bar(3) {
// Do some calculations with an array and return it.
}
Then in foo() I can have the following code:
foo(void* ret_val, int mode, int num_params, ...) {
va_list args;
va_start(args, num_params);
switch (mode) {
case 1: {
int a = va_arg(args, int);
int b = va_arg(args, int);
bar1(a, b);
}
break;
case 2: {
int val = bar1();
*(int*)ret_val = val;
}
break;
case 3: {
int* p = new int[10];
p = bar3();
// Add a loop to test out that the array has been read from bar3(), which works.
*(int*)ret_val = *p; // <== This is where the problem is.
}
break;
}
va_end(args);
}
Then in the main program I can invoke foo() in the following way:
int x;
foo(&x, 1, 2, 10, 20); // Call bar1()
foo(&x, 2, 0); // Call bar2()
printf("%d\n", x);
int xd[10]; // Declare and initialize xd.
for (int i = 0; i < 10; i++) {
xd[i] = 0;
}
foo(xd, 3, 0) // Call bar3()
for (int i = 0; i < 10; i++) {
printf("%d %d\n", i, xd[i]);
}
I put in the calls for bar1() and bar2() for context, and they work. For bar1() two ints are provided, but nothing is returned, and a dummy output argument has to be provided. For bar2() no input values are given, but an output int is returned, which is cast to star(int star) which works and is returned correctly.
However, for bar3() internally I generate a 10 element array as a test, which is correctly returned inside foo() from the print statement, but I am unable to return the array to main(). I have fiddled around with various statements involving pointers, but either a list of zeros is returned if the array is initialized, or garbage if it is not.
How can I return an array correctly?
In this call
foo(xd, 3, 0)
the array designator xd is converted to pointer to its first element and the function deals with a copy of this value.
Within the function this statement
*(int*)ret_val = *p;
just changes the first element of the array xd with the value of the first element of the array pointed to by the pointer p.
Arrays do not have the copy assignment operator. You can not assign one array to another as for example
int a[10] = { /*...*/ };
int b[10] = { /*...*/ };
a = b;
So this code snippet
int* p = new int[10];
p = bar3();
// Add a loop to test out that the array has been read from bar3(), which works.
*(int*)ret_val = *p;
does not make a sense. Moreover it seems there is a memory leak because at first the pointer p was assigned with the address of the allocated memory
int* p = new int[10];
and then reassigned with the value returned by the function bar3.
p = bar3();
You can write foo as shown below (in C, as this question was originally tagged). Comments show how to think about ret_val. Note that the interface for bar3 has been changed.
/* ret_val is a pointer to some type T, a "T *", that has been converted to
"void *". To use it, we convert it back to its original type "T *".
*/
foo(void *ret_val, int mode, int num_params, ...)
{
va_list args;
va_start(args, num_params);
switch (mode)
{
case 1:
{
// T is void. Nothing is returned via ret_val.
int a = va_arg(args, int);
int b = va_arg(args, int);
bar1(a, b);
}
break;
case 2:
{
/* We will return an int, so T is an int, and we convert ret_val
back to "int *".
*/
int val = bar1();
// Return val.
* (int *) ret_val = val;
}
break;
case 3:
{
/* We will return a pointer to an int, so T is an "int *", and
we convert ret_val back to "int **".
int *p = malloc(10 * sizeof p);
if (!p)
{
fprintf(stderr, "Error, memory allocation failed.\n");
exit(EXIT_FAILURE);
}
bar3(p);
// Return p.
* (int **) ret_val = p;
}
break;
}
va_end(args);
}
Then, for case 3, you can call foo with:
int *xd;
foo(&xd, 3, 0);

Pointing to static arrays, but dereferencing without the use of *

I have a series of NX objects (e.g., a static bool array of dimension [NX][N1][N2] in the example below).
I would like to loop over these objects. At each iteration, an object called 'A' is to function as a surrogate for the corresponding element 'B[x]' in the series.
However, the code inside the loop is legacy code, so we cannot really change how we refer to 'A' itself
const int NX = ...;
const int N1 = ...;
const int N2 = ...;
bool B[NX][N1][N2];
Code_needed: declare A here (maybe first defining a class template?)
int main(){
for(int x = 0; x < NX; ++x){
Code_needed: make A refer to B[x] here (maybe A = &B[x])
// In the following, "A[i][j]" should refer to B[x][i][j]...
A[3][5] = true; // This is legacy code, so we cannot change it
// (e.g., cannot add a * in front of A)
}
}
Note that the types of objects on which I want to apply this are heavy, such as arrays of containers, so copying them over inside the loop is not acceptable. Maximizing performance is generally of interest in this application.
Would appreciate the help!!
EDIT: How would the answer be affected, if A were to be a scalar (i.e., it is B[NX] only)?
You can define a reference to a two-dimensional array inside the for loop:
bool (&A)[N1][N2] = B[x];
Now A[i][j] is equivalent to B[x][i][j].
Note that you cannot move the definition of A outside the for loop, because references have to be initialized when they are defined, and they cannot be rebound later.
If you need to define A outside the for loop and reassign inside the for loop, use a pointer instead:
// outside the for loop
bool (*A)[N2];
// inside the for loop
A = B[x];
And here is a complete code example which compiles just fine on my compiler:
const int NX = 3;
const int N1 = 5;
const int N2 = 7;
bool B[NX][N1][N2];
bool (*A)[N2];
int main()
{
for (int x = 0; x < NX; ++x)
{
A = B[x];
A[3][5] = true;
}
}
You can also write an alias class template which overloads the assignment operator appropriately:
template <typename T>
class alias
{
T* p;
alias(const alias&);
alias& operator=(const alias&);
public:
alias() : p(0) {}
void rebind(T& x)
{
this->p = &x;
}
void operator=(const T& x)
{
*p = x;
}
operator T&()
{
return *p;
}
};
This works with arrays:
bool B[NX][N1][N2];
alias<bool[N1][N2]> A;
// ...
A.rebind(B[x]);
A[3][5] = true;
And plain bools:
bool B[NX];
alias<bool> A;
// ...
A.rebind(B[x]);
A = true;

combining similar functions into one common function involving passing function pointers as parameters

I am trying to combine the following two functions into one portable function:
void NeedleUSsim::FindIdxRho()
{
searchTmp = &ninfo->rho;
double *p = std::find_if(tplRho_deg, tplRho_deg+sampleDim[2], &NeedleUSsim::GreaterThanOrEqualTo);
while(p != tplRho_deg+sampleDim[2])
{
idxRho = p - tplRho_deg;
p = std::find_if(p+1, tplRho_deg+sampleDim[2], &NeedleUSsim::GreaterThanOrEqualTo);
}
}
void NeedleUSsim::FindIdxDepth()
{
searchTmp = &ninfo->l;
double *p = std::find_if(tplL, tplL+sampleDim[1], &NeedleUSsim::LessThanOrEqualTo);
while(p != tplL+sampleDim[1])
{
idxL = p - tplL;
p = std::find_if(p+1, tplL+sampleDim[1], &NeedleUSsim::LessThanOrEqualTo);
}
}
Ideally, I want the parameters of the function to have tpl member to be passed as a pointer, with the size and rho/l passed as value. searchTmp is a file scope double precision pointer. Is there any easy way of passing &NeedleUSsim::GreaterThanOrEqualTo function as a parameter of the function that I'm trying to write easily?
Thanks in advance for the advice.
The simplest way to make your code a bit more generic is the following :
template<typename ComparisonType>
double* NeedleUSsim::FindIdx(double* containerBegin, double* containerEnd, ComparisonType comparison) {
double* p = std::find_if(containerBegin, containerEnd, comparison);
double* idx = 0;
while(p != containerEnd)
{
idx = p - containerBegin;
p = std::find_if(p+1, containerEnd, comparison);
}
return idx;
}
void NeedleUSsim::FindIdxRho()
{
searchTmp = &ninfo->rho;
double* idx = FindIdx(tplRho_deg, tplRho_deg+sampleDim[2], &NeedleUSsim::GreaterThanOrEqualTo);
if( idx != 0 )
{
idxL = idx;
}
}
void NeedleUSsim::FindIdxDepth()
{
searchTmp = &ninfo->l;
double* idx = FindIdx(tplL, tplL+sampleDim[1], &NeedleUSsim::LessThanOrEqualTo);
if( idx != 0 )
{
idxRho = idx;
}
}
Is there any easy way of passing &NeedleUSsim::GreaterThanOrEqualTo function as a parameter of the function that I'm trying to write easily?
There's a couple ways to do this.
You can pass the function pointer around
You can create and pass a function object using run-time polymorphism
You can make your common function templated on a function object (compile time polymorphism)
The first method is covered above by eJames.
Option 2
The second method involves wrapping your comparison functions in some function-object hierarchy. A function object is an instance of a class with the () operator overloaded. This makes the instance callable:
class IComparator
{
public:
virtual bool operator()(lhs, rhs) = 0;
}
class CComparatorLessThan : public IComparator
{
public:
virtual bool operator()(lhs, rhs) {...}
}
class CComparatorGreaterThan : public IComparator
{
public:
virtual bool operator()(lhs, rhs) {...}
}
Your common function would take an ICompatator reference and the behavior would be dynamically bound at runtime.
Option 3
The third method involves templatizing instead of creating an object hierarchy
template <class Comparator>
void foo(...)
{
...
Comparator comparer;
std::find_if(..., comparer);
}
then calling foo would involve:
foo<CComparatorGreaterThan>(...);
This eliminates a lot of the runtime overhead of the second solution. Here you don't have to define the base class. You only have to have some kind of class that has operator() overloaded and will return bool.
It is possible to pass a member function pointer to a function as follows:
typedef bool (NeedleUSsim::*compFunctionPtr)(NeedleUSsim &x, NeedleUSsim &y);
void NeedleUSsim::FindIdxRho(compFunctionPtr comparison)
{
//..
p = std::find_if(tplRho_deg, tplRho_deg+sampleDim[2], comparison);
//..
}
Which can then be called like so:
//..
someNeedleUSsim.FindIdxRho(&NeedleUSsim::LessThanOrEqualTo);
//..
Have a look at this C++ FAQ Lite article for more information.
The easy way to take functions and more complex parameters into a function is to template them (I'm guessing at some of the parameter types)
template <typename F>
void NeedleUSsim::FindIdx(double *ninfoMember, double *tplParam, size_t dimension, F CompareFunc, int &target)
{
searchTmp = ninfoMember;
double *p = std::find_if(tplParam, tplParam+sampleDim[dimension], CompareFunc);
while(p != tplParam+sampleDim[dimension])
{
target= p - tplParam;
p = std::find_if(p+1, tplParam+sampleDim[dimension], CompareFunc);
}
}
Then call it:
FindIdx(&ninfo->rho, tplRho_deg, 2, &NeedleUSsim::GreaterThanOrEqualTo, idxRho);
FindIdx(&ninfo->l, tplL, 1, &NeedleUSsim::LessThanOrEqualTo, idxL);
double *p = std::find_if(b, e, &NeedleUSsim::GreaterThanOrEqualTo);
while(p != e)
{
idxRho = p - b;
p = std::find_if(p + 1, e, &NeedleUSsim::GreaterThanOrEqualTo);
}
Note that this loop that you use is not necessary. Use reverse iterators
std::reverse_iterator<double*> rb(e), re(b);
rb = std::find_if(rb, re, &NeedleUSsim::GreaterThanOrEqualTo);
if(rb != re) {
idxRho = re - rb;
}
Now its more obvious what it does. If writing to idxRho only when something was found was a mistake or doesn't matter, you can shorten it to this
std::reverse_iterator<double*> rb(e), re(b);
idxRho = re - std::find_if(rb, re, &NeedleUSsim::GreaterThanOrEqualTo);