C++ Passing args to void function - c++

How can I pass args to this function:
int myClass::myFunc(void * aArgs){
return 0;
}
I call it this way:
thrd_create(&t, myClass::myFunc, (void*)0);
I need to pass multiple arguments to the function, how can I achieve it?

There are plenty of ways. For example:
struct Arg_Struct
{
int m_nArg1;
float m_fArg2;
bool m_bArg3;
}
//...
Arg_Struct* pStruct = new Arg_Struct;
pStruct->m_nArg1 = 0;
thrd_create(&t, myClass::myFunc, (void*)pStruct);
//...
int myClass::myFunc(void * aArgs){
Arg_Struct* pArgs = (Arg_Struct*)aArgs;
int n = pArgs->m_nArg1;
//...
return 0;
}

Related

How to pass reference to a vector as variadic argument?

class Hex
{
short type;
Hex(short typE)
{
type = typE;
}
}
vector< vector<Hex> > hexes;
void HexRings(sf::Vector2i pos, void operation(sf::Vector2i, va_list), ...)
{
va_list args;
va_start(args, operation);
//block of irrelevant changes of pos
operation(pos, args);
//another block of irrelevant changes of pos
va_end(args);
}
void MakeHexTypeX(sf::Vector2i pos, va_list args)
{
hexes[pos.x][pos.y].type = va_arg(args, int);
}
void AddHexes(sf::Vector2i pos, va_list args)
{
vector<sf::Vector2i> returnThat;
returnThat = va_arg(args, vector<sf::Vector2i>());// how to make this line actually give back a reference to the original vector (visited)
list.push_back(sf::Vector2i(pos.x, pos.y));
}
int main()
{
vector<sf::Vector2i> visited;
for(int y=0; y<10; ++y)
{
hexes.push_back(vector<Hex>());
for(int x=0; x<10; ++x) hexes[x].push_back(Hex(0));
}
HexRings(sf::Vector2i(5, 5), AddHexesOfTypeX, visited);
HexRings(sf::Vector2i(5, 5), MakeHexTypeX, 1);
}
I have a function (HexRings), that iterates in a specific pattern on a two-dimensional vector. I want to have an ability to pass to this function a pointer to another function (like MakeHexTypeX or AddHexes), that performs a certain action on every visited tile. Everything is fine, if this function is changing the map, but I don't know what to do, if this function has to report back. For example, if I want to get all hexes of type X, that HexRings has encountered, the vector would have to be passed as reference, which I don't even know how to write.
TL;DR: How to pass reference to a vector as variadic argument?
Instead of passing the operation function into HexRings, I would pass a reference to a functor. Functors can store state and thus hold the vector you wish. Here we go:
struct processor {
// you will be overriding this for every different operation you want to perform
virtual void operator()(sf::Vector2i, va_list) = 0;
};
struct make_hex_type_x
: public processor {
void operator()(sf::Vector2i pos, va_list args) override {
hexes[pos.x][pos.y].type = va_arg(args, int);
}
};
struct add_hexes
: public processor {
private:
// this is our state
vector<sf::Vector2i> returnThat;
public:
void operator()(sf::Vector2i pos, va_list args) override {
returnThat = va_arg(args, vector<sf::Vector2i>());
list.push_back(sf::Vector2i(pos.x, pos.y));
}
// get access to your return vector
vector<sf::Vector2i>& get() {
return returnThat;
}
};
//now change HexRings so that it accepts the functor instead of a function
void HexRings(sf::Vector2i pos, processor& pr, ...)
{
va_list args;
va_start(args, operation);
//block of irrelevant changes of pos
pr(pos, args);
//another block of irrelevant changes of pos
va_end(args);
}
// and finally call as follows
int main()
{
vector<sf::Vector2i> visited;
for(int y=0; y<10; ++y)
{
hexes.push_back(vector<Hex>());
for(int x=0; x<10; ++x) hexes[x].push_back(Hex(0));
}
make_hex_type_x p1;
add_hexes p2;
HexRings(sf::Vector2i(5, 5), p2, visited);
HexRings(sf::Vector2i(5, 5), p1, 1);
// now extract your vector
auto& vec = p2.get();
}

function pointer for different functions with different data types or parameter

i have this code which uses a function pointer to point 3 functions sum, subtract, mul. it works well. but now the problem is that i have functions with different no.of parameters and different data types. how to implement this.
int add(int a, int b)
{
cout<<a+b;
}
int subtract(int a, int b)
{
cout<<a-b;
}
int mul(int a, int b)
{
cout<<a*b;
}
int main()
{
int (*fun_ptr_arr[])(int, int) = {add, subtract, mul};
unsigned int ch, a = 15, b = 10,c=9;
ch=2;
if (ch > 4) return 0;
(*fun_ptr_arr[ch])(a, b);
return 0;
}
The simple answer is that technically you can't do this. You could do some manipulations using an array as input for all these functions, but you will still have to know exactly what to pass to each function. From a software engineering perspective, you should not do this - I suggest you take a look at the nice answers here: C++ Function pointers with unknown number of arguments
A slightly different approach using objects to implement the required behavior. In order to have a truly generic kind of solution, we need to use Interfaces.
Dismantle the data and operation i.e keep them separately.
//Interface which describes any kind of data.
struct IData
{
virtual ~IData()
{
}
};
//Interface which desribes any kind of operation
struct IOperation
{
//actual operation which will be performed
virtual IData* Execute(IData *_pData) = 0;
virtual ~IOperation()
{
}
};
Now, every operation knows the kind of data it work on and will expect that kind of data only.
struct Operation_Add : public IOperation
{
//data for operation addition.
struct Data : public IData
{
int a;
int b;
int result;
};
IData* Execute(IData *_pData)
{
//expected data is "Operation_Add::Data_Add"
Operation_Add::Data *pData = dynamic_cast<Operation_Add::Data*>(_pData);
if(pData == NULL)
{
return NULL;
}
pData->result = pData->a + pData->b;
return pData;
}
};
struct Operation_Avg : public IOperation
{
//data for operation average of numbers.
struct Data : public IData
{
int a[5];
int total_numbers;
float result;
};
IData* Execute(IData *_pData)
{
//expected data is "Operation_Avg::Data_Avg"
Operation_Avg::Data *pData = dynamic_cast<Operation_Avg::Data*>(_pData);
if(pData == NULL)
{
return NULL;
}
pData->result = 0.0f;
for(int i = 0; i < pData->total_numbers; ++i)
{
pData->result += pData->a[i];
}
pData->result /= pData->total_numbers;
return pData;
}
};
Here, is the operation processor, the CPU.
struct CPU
{
enum OPERATION
{
ADDITION = 0,
AVERAGE
};
Operation_Add m_stAdditionOperation;
Operation_Avg m_stAverageOperation;
map<CPU::OPERATION, IOperation*> Operation;
CPU()
{
Operation[CPU::ADDITION] = &m_stAdditionOperation;
Operation[CPU::AVERAGE] = &m_stAverageOperation;
}
};
Sample:
CPU g_oCPU;
Operation_Add::Data stAdditionData;
stAdditionData.a = 10;
stAdditionData.b = 20;
Operation_Avg::Data stAverageData;
stAverageData.total_numbers = 5;
for(int i = 0; i < stAverageData.total_numbers; ++i)
{
stAverageData.a[i] = i*10;
}
Operation_Add::Data *pResultAdd = dynamic_cast<Operation_Add::Data*>(g_oCPU.Operation[CPU::ADDITION]->Execute(&stAdditionData));
if(pResultAdd != NULL)
{
printf("add = %d\n", pResultAdd->result);
}
Operation_Avg::Data *pResultAvg = dynamic_cast<Operation_Avg::Data*>(g_oCPU.Operation[CPU::AVERAGE]->Execute(&stAverageData));
if(pResultAvg != NULL)
{
printf("avg = %f\n", pResultAvg->result);
}
If you have the following functions
int f1(int i);
int f2(int i, int j);
You can define a generic function type like this
typedef int (*generic_fp)(void);
And then initialize your function array
generic_fp func_arr[2] = {
(generic_fp) f1,
(generic_fp) f2
};
But you will have to cast the functions back
int result_f1 = ((f1) func_arr[0]) (2);
int result_f2 = ((f2) func_arr[1]) (1, 2);
Obviously, it does not look like a good way to build a program
To make code look a little bit better you can define macros
#define F1(f, p1) ((f1)(f))(p1)
#define F2(f, p1, p2) ((f2)(f))(p1, p2)
int result_f1 = F1(func_arr[0], 2);
int result_f2 = F2(func_arr[1], 1, 2);
EDIT
Forgot to mention, you also have to define a type for every type of function
typedef int (*fi)(int); // type for function of one int param
typedef int (*fii)(int, int); // type for function of two int params
And to then cast stored pointers to those types
int result_f1 = ((fi) func_arr[0]) (2);
int result_f2 = ((fii) func_arr[1]) (1, 2);
Here is a complete example
#include <iostream>
typedef int (*generic_fp)(void);
typedef int (*fi)(int); // type for function of one int param
typedef int (*fii)(int, int); // type for function of two int params
#define F1(f, p1) ((fi)(f))(p1)
#define F2(f, p1, p2) ((fii)(f))(p1, p2)
int f1(int i);
int f2(int i, int j);
int main()
{
generic_fp func_arr[2] = {
(generic_fp) f1,
(generic_fp) f2
};
int result_f1_no_macro = ((fi) func_arr[0]) (2);
int result_f2_no_macro = ((fii) func_arr[1]) (1, 2);
int result_f1_macro = F1(func_arr[0], 2);
int result_f2_macro = F2(func_arr[1], 1, 2);
std::cout << result_f1_no_macro << ", " << result_f2_no_macro << std::endl;
std::cout << result_f1_macro << ", " << result_f2_macro << std::endl;
return 0;
}
int f1(int i)
{
return i * 2;
}
int f2(int i, int j)
{
return i + j;
}
The code above produces the following output
4, 3
4, 3

How can I access a member of a class from a function via pointer?

I wish to
create an array of class/struct items (c1)
then create an array of pointer to the original array (*cp1), which can be sorted
then access members of the class from within a function.
However I'm getting stuck at the initial function call.
Here's my basic code:
struct Car
{
int speed;
};
Car c1[5];
Car *cp1[5];
int main() {
for (int i=0;i<5;i++) {
c1[i].speed = i;
cp1[i] = &c1[i];
}
garage(cp1, 5);
}
void garage(Car **ar, int n) {
int p = (*ar[n / 2])->speed;
}
First of all, your garage function is not known to the compiler at the place where you call it, since it is defined below main. To fix it, either place the function definition above main, or introduce it with a prototype.
Second, at the line int p = (*ar[n / 2])->speed;, *ar[n/2] is not a pointer, so you should use . instead of ->, as in int p = (*ar[n / 2]).speed;
Funcion garage must be declared before you can refer it.
void garage(Car **ar, int n);
int main()
{
//...
}
void garage(Car **ar, int n) {
//...
}
Function main in C++ shall have return type int
int main()
{
//...
}
And within the function the correct expression will look
void garage(Car **ar, int n) {
int p = (*ar )[n / 2]).speed;
}
Or
void garage(Car **ar, int n) {
int p = ar[n / 2]->speed;
}
Or
void garage(Car **ar, int n) {
int p = ( *ar[n / 2] ).speed;
}
struct Car
{
int speed;
};
Car c1[5];
Car *cp1[5];
void garage(Car **ar, int n); // forward declare garage
int main()
{
for (int i=0;i<5;i++) {
c1[i].speed = i;
cp1[i] = &c1[i];
}
garage(cp1, 5);
}
void garage(Car **ar, int n) {
int p = ar[n / 2]->speed; // -> dereferences the pointer, you don't need to
}

Passing and Assigning New Value to Pointer C++

I'm passing a pointer to a function. I'd like to assign a new address to the passed pointer inside the function, and I'd like that address to be used after the function returns. I'm not sure if this is possible, but I'd like to do:
int main()
{
int i = 100, j = 200;
int * intPtr = &i;
foo(intPtr, j);
// I want intPtr to point to j, which contains 200 after returning from foo.
}
void foo( int * fooPtr, int & newInt )
{
int * newIntPtr = &newInt;
fooPtr = newIntPtr;
}
Is this possible, or will intPtr not maintain the new assignment after returning from foo? Could this work (if it doesn't: why)?
Pass a reference to the pointer:
void foo( int *& fooPtr, int & newInt )
The reason why your method does not work is that you're passing the pointer by-value. Passing by-value creates a temporary within the function, so as soon as the function returns, any changes to the temporary go away.
It is no different than this:
void foo(int x)
{
x = 10;
}
int main()
{
int a = 0;
foo( a );
// a is still 0, not 10
}
The a is passed by value, so the foo() function changes the parameter to 10 within the function. However, you will see that a in main does not change to 10 after the function returns.
To change a, you need to pass the int by reference:
void foo(int& x)
{
x = 10;
}
int main()
{
int a = 0;
foo( a );
// a is now 10
}
Pass a pointer of the pointer and assign to it
int main()
{
int i = 100, j = 200;
int * intPtr = &i;
foo( &intPtr, j );
// I want intPtr to point to j, which contains 200 after returning from foo.
}
void foo( int ** fooPtr, int & newInt )
{
int * newIntPtr = newInt;
*fooPtr = newIntPtr;
}
If you programing in pure C you can do like this
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void foo(int **, int *);
int main()
{
int i = 100, j = 200;
int * intPtr = &i;
int *intPtr2=&j;
foo( &intPtr, intPtr2 );
// I want intPtr to point to j, which contains 200 after returning from foo.
printf("%d",*intPtr);
}
void foo( int ** fooPtr, int * newInt )
{
int * newIntPtr = newInt;
*fooPtr = newIntPtr;
}

Call map key to invoke function requiring a parameter - how to get working

Here is my code.
#include <map>
#include <string>
#include <algorithm>
class maptest {
public:
int doubler(int val) { return val * 2; }
int halver(int val) { return val / 2; }
int negativer(int val) { return val > 0 ? -val : val; }
};
int main() {
const char* const ID[] = {"doubler", "halver", "negativer" };
int ID_SIZE = sizeof(ID) / sizeof(*ID);
//signature of maths functions
typedef int (maptest::*mathfunc)(int);
mathfunc mfuncs[] = { &maptest::doubler, &maptest::halver, &maptest::negativer};
std::map<std::string, mathfunc> mathmap;
for(int i = 0; i < ID_SIZE; ++i) {
mathmap.insert(std::make_pair(ID[i], mfuncs[i]));
}
//C2064: term does not evaluate to a function taking 1 argument
int result = *mathmap["doubler"](3);
return 0;
}
I think this would work if there was no parameter to be passed to the functions. But how do I pass a parameter in this way?
Your mathfuncs are member functions, so you need an object on which to invoke them:
maptest mt;
int result = (mt.*(mathmap["doubler"]))(3);
Alternatively, you could make your member functions static:
class maptest {
public:
static int doubler(int val) { return val * 2; }
static int halver(int val) { return val / 2; }
static int negativer(int val) { return val > 0 ? -val : val; }
};
And then define mathfunc accordingly:
typedef int (*mathfunc)(int);
And this would allow you to invoke them the way you are invoking them in your original post:
typedef int (*mathfunc)(int);
Notice, that a way to make this design more flexible is to make use of std::function, which would allow you to pass any type of callable object. For instance:
typedef std::function<int(int)> mathfunc;
mathfunc mfuncs[] = {
&maptest::doubler,
&maptest::halver,
&maptest::negativer,
[] (int i) { return i * 2; } // <== A LAMBDA...
};
You are invoking non static member function.
do the following.
maptest t;
int (maptest::*tptr) (int) = mathmap["doubler"];
int result = (t.*tptr)(2);
Hope this helps.