I have class
Class A{
};
typedef struct
{
const char *dec_text;
void (A::*TestFun)();
} Test ;
Test _funs[] = {{"testLogOK", &A::testLogOK},
{"testLoginException", &A::testLoginException}
};;
How can i initialize this Test Array in construct method. The _funs tracks the A's method name and corresponding address, the methods which like:
void (methodName) (void)
In construction method, both below ways fail:
_funs = {{"testLogOK", &A::testLogOK},
{"testLoginException", &A::testLoginException}
};
The other question is how can i invoke the function pointer.. I tried the way like:
int
A::run (const char *name, int argc, ACE_TCHAR *argv[])
{
for(int i=0; i< sizeof(_funs)/sizeof(Test); i++){
Test test = _funs[i];
*(test.testFun)(); //this->*(test.fun)(); Both fail with same error
//(this->*(test.fun))() works
}
}
The compile also fails with message:
error C2064: term does not evaluate to a function taking 0 arguments
[UPdate]
I removed the struct Test and Test _funs out of Class A. But still have problem in A's method:
int A::run (const char *name, int argc, ACE_TCHAR *argv[])
The testLogOK and testLoginException method do exist as member functions of class A
Try this:
class A
{
public:
struct Test
{
const char *dec_text;
void (A::*TestFun)();
};
A(Test tt[])
{
for (int i=0; tt[i].dec_text; i++)
_funs[i] = tt[i];
}
void f1() { printf("this is f1\n"); }
void f2() { printf("this is f2\n"); }
void f3() { printf("this is f3\n"); }
Test _funs[100];
};
A::Test tt[] =
{
{ "Function f1", &A::f1},
{ "Function f2", &A::f2},
{ "Function f3", &A::f3},
{0, 0}
};
void test()
{
A a(tt);
(a.*(a._funs[0].TestFun))();
A *pa = new A(tt);
(pa->*(pa->_funs[1].TestFun))();
delete pa;
// EDIT: call f3
(a.*(tt[2].TestFun))(); // this will call directly from the global table
}
This will invoke the function assigned to the pointer.
This can be improved quite a bit if you typedef the pointer to the member
typedef void (A::*PF_T)();
and use a std::map as container:
std::map<std::string, PF_T> func_map;
It can be streamlined a lot more, but I hope it helps up to this point.
Related
How can one pass a non moveable object to a std::function? One easy enough alternative is passing a std::reference_wrapper which would create the need for the lifecycle of function be dependant on the object. Example code follows to explain the issue better.
class Player {
std::atomic_int runs {0};
std::string name;
public:
Player(std::string&& name) : name(std::move(name)) {} //...
void inc() { ++runs;}
};
class PlayerStats {
std::array<std::unique_ptr<Player>,2> players;
public:
PlayerStats() {
for(int i = 0; i<2 ; i++)
players[i] = std::unique_ptr<Player>(new Player{"player"+std::to_string(i)});
}
Player* const operator() (int index) const {
return players[index].get();
}
};
using player_total_f = std::function<Player* const(int index)>;
class GameStats {
std::string game;
std::string date;
player_total_f f;
public:
GameStats(std::string&& game, std::string&& date, player_total_f&& _f) :
game(std::move(game)), date(std::move(date)), f(std::move(_f)) {}
};
int main(int argc, char *argv[])
{
PlayerStats st;
//GameStats("game1","10.11",std::ref(st)); //this seems like the only possibility, no way to make GameStats own the functor
return 0;
}
How can I set the function here to PlayerStats, given that it is non copyable, a std::ref seems to be like the only possibility?
template<class F>
auto shared_function( F&& f ){
auto spf=std::make_shared<std::decay_f<F>>(std::forward<F>(f));
return [spf=std::move(spf)](auto&&...args)->decltype(auto){
return (*pf)(decltype(args)(args)...);
};
}
own it in a shared ptr. Changes semantics a bit, but fixes it.
Or write your own non-copying std function.
I have 2 functions with the same input and output types.
uint32_t doWork(uint32_t time);
uint32_t MyClass::DoWork(uint32_t time);
now I want to dependency inject this function into another class to either use one of the functions.
So I thought I could use a function point but this is not working since a function pointer requires the class type to also be used.
Is there any way to store both functions in the same function pointer type and pass it to a constructor?
The function from the class is not static.
Any help is appreciated!
I experimented a little bit with my C++ compiler.
Here is what I got that seems to be doing the job:
#include <stdio.h>
typedef unsigned int uint32_t;
typedef uint32_t (doWorkPtr) (uint32_t time);
uint32_t doWork(uint32_t time) {
return time*2;
}
class MyClass {
public:
int times;
int DoWork(uint32_t time) { return time*times; }
};
struct Adapter {
MyClass* a;
doWorkPtr* ptr;
int operator() (uint32_t time) {
if(a)
return a->DoWork(time);
else
return ptr(time);
}
};
int main(int argc, char** argv) {
Adapter* pointers[2];
MyClass klass;
klass.times = 3;
Adapter adapter;
adapter.a = &klass;
adapter.ptr = 0;
Adapter adapter2;
adapter2.a = 0;
adapter2.ptr = &doWork;
pointers[0] = &adapter;
pointers[1] = &adapter2;
printf("result1 %i\n", (*pointers[0])(1));
printf("result2 %i\n", (*pointers[1])(1));
return 0;
}
Your class would store 'Adapter' pointers instead of plain functions pointers when using this.
Hope it helps!
Here is some code:
typedef void (*ACallBack)(int i);
class SomeClass
{
private:
ACallBack aCallBack;
public:
void SetCallBack(ACallBack aCallBack);
};
void SomeClass::SetCallBack(ACallBack aCallBack)
{
this->aCallBack = aCallBack;
}
class SomeOtherClass
{
private:
SomeClass someClass;
public:
void InitializeSomeClass();
private:
void callBackMethod(int i);
};
void SomeOtherClass::InitializeSomeClass()
{
this->changeVariable = 10;
this->someClass.SetCallBack(this->callBackMethod); // DOESN'T WORK
this->someClass.UseCallBack();
}
void SomeOtherClass::callBackMethod(int i)
{
}
void globalCallBack(int i)
{
int myInt = i;
}
int main()
{
SomeClass sC;
sC.SetCallBack(globalCallBack); //WORKS!!
}
Basically if I try to set my callback function in SomeOtherClass it doesn't work but when I set it globally in main it does. What am I missing here?
Just use std::function and std::bind():
typedef std::function<void(int i)> ACallBack;
// old code pretty much the same
int main()
{
using namespace std::placeholders;
SomeClass sC;
sC.SetCallBack(globalCallBack); //WORKS!!
SomeOtherClass oC;
sC.SetCallBack(std::bind(&SomeOtherClass::callBackMethod,oC,_1)); //WORKS AS WELL!!
}
In this case you do not really need to pass void *userData but may add it as well if you need old code to compile.
You have to make the method static:
static void callBackMethod(int i, void* userData);
if you need a pointer to a method that is not static, ie an instance method, it becomes more complex.
typedef void ( myclass::*FUNC ) (int i, void* userData);
and if you want to use it, it becomes a hastlle :
myclass obj; // instantiate myclass
FUNC f = &myclass::myfunc; // assign address
( obj.*f ) ( 123, NULL ); // and call it
I need some help on a strange mix between function pointers and templates...
My target :
You have a class : template<typename B> class A, and A instanciate a B member. Now I want to acces B getter/setter.
I tried this :
class B_example
{
public:
B_example(int v):m_var(v){}
int getVar() { return m_var; }
void setVar(int v) { m_var = v; }
private:
int m_var;
};
template<typename B> class A
{
public:
A():m_b(B(5))
{
get = &m_b.getVar;
set = &m_b.setVar;
}
int (B::*get)();
void (B::*set)(int);
private:
B m_b;
};
int main(int argc, char** argv)
{
A<B_example> A_instance;
B_example B_instance(5);
int a = (A_instance.get*)();
std::cout << a << std::endl;
}
Thank's for any help.
Alexandre
First, fix the syntax errors:
get = &B::getVar;
set = &B::setVar;
Then, the member-function pointer needs to be called on an object. Without knowing the purpose of these strange pointers, I can't guess what you want to do here. Maybe you want to call on B_instance:
int a = (B_instance.*A_instance.get)();
Or maybe you want to call it on the m_b object within A_instance; but you can't do that because it's private. If that's the case, you probably just want regular member functions, rather than weird function pointers
int get() {return m_b.getVar();}
void set(int v) {m_b.setVar(v);}
These:
get = &m_b.getVar;
set = &m_b.setVar;
Should be:
get = &B::getVar;
set = &B::setVar;
And (A_instance.get*)() should be (B_instance.*A_instance.get)().
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
What does it mean to have an undefined reference to a static member?
I don't know why I got error "undefined reference to `TT::i'" if I implement the function outside of class declaration?
Here is the code..
class TT{
private:
static int i;
public:
void t();
};
void TT::t(){
i=0;
}
It's nothing to do with where you defined the function, it's that you didn't define the static member variable, you only declared it. You need to put its definition outside the class, e.g.
int TT::i;
undefined reference to `TT::i'
is because you havent defined the static data member outside class. All static data members have to be defined outside class before using them.
class TT
{
private:
static int i;
public:
void t();
};
void TT::t()
{
i=0;
}
int TT::i=0; // define it outside the class. and if possible initialize
Static variables are saved in a different part of memory than any instance of a class. This is because they are not a PART of an instance of any class.
The code below compiles because the function t is never called.
class TT
{
private:
static int i;
public:
void t()
{
i=0;
}
};
int main(int argc, char *argv[])
{
qWarning() << "hi";
TT * t = new TT();
//t->t();
return 0;
}
However, this code doesn't complie, because t is called
class TT
{
private:
static int i;
public:
void t()
{
i=0;
}
};
int main(int argc, char *argv[])
{
qWarning() << "hi";
TT * t = new TT();
t->t();
return 0;
}
You are allowed to have undefined references you don't use in C++ (and C for that matter). For some reason, I am unsure of, the compiler seems to think this code is referencing i, when the stuff above that complies was not referencing it until called (any ideas as to why)?
class TT
{
private:
static int i;
public:
void t();
};
//int TT::i = 0;
void TT::t(){
i=0;
}
Functional example, with the static defined:
class TT
{
private:
static int i;
public:
void t();
};
int TT::i = 0;
void TT::t(){
i=0;
}