How do you declare a const array of function pointers? - c++

Firstly, I've got functions like this.
void func1();
void func2();
void func3();
Then I create my typedef for the array:
void (*FP)();
If I write a normal array of function pointers, it should be something like this:
FP array[3] = {&func1, &func2, &func3};
I want to make it a constant array, using const before "FP", but I've got this error messages:
error: cannot convert 'void ( * )()' to 'void ( * const)()' inialization
PD: Sorry my bad English.
EDIT:
x.h
typedef void (*FP)();
class x
{
private:
int number;
void func1();
void func2();
void func3();
static const FP array[3];
}
x.cpp
const FP x::array[3] = {&x::func1, &x::func2, &x::func3};
My code is more large and complex, this is a summary

Then I create my typedef for the array:
void (*FP)();
Did you miss typedef before void?
Following works on my compiler.
void func1(){}
void func2(){}
void func3(){}
typedef void (*FP)();
int main()
{
const FP ar[3]= {&func1, &func2, &func3};
}
EDIT (after seeing your edits)
x.h
class x;
typedef void (x::*FP)(); // you made a mistake here
class x
{
public:
void func1();
void func2();
void func3();
static const FP array[3];
};

without typedef:
void (*const fp[])() = {
f1,
f2,
f3,
};

typedef void (*FPTR)();
FPTR const fa[] = { f1, f2};
// fa[1] = f2; You get compilation error when uncomment this line.

Which compiler are you using? This works on VS2005.
#include <iostream>
void func1() {std::cout << "func1" << std::endl;}
void func2() {std::cout << "func2" << std::endl;}
void func3() {std::cout << "func3" << std::endl;}
int main()
{
int ret = 0;
typedef void (*FP)();
const FP array[3] = {&func1, &func2, &func3};
return ret;
}

If you want the array itself to be const:
FP const a[] =
{
func1,
func2,
func3
};

Related

Populating a wrapper class with pass-through methods

I inherited a large rather-old C++98 codebase which is now luckily using C++17. I have an interface in a header file interfaceHeader.h as follows:
struct PluginInterface {
void (*method1)(bool enabled);
void (*method2)(int param1, int param2);
bool (*method3)(const char *path, const int& val);
};
then in another source cpp file:
MyImplementingClass *gClass = new gClass();
void method1(bool enabled) {
gClass->method1(enabled);
}
void method2(int p1, int p2) {
gClass->method2(p1, p2);
}
bool method3(const char *path, const int& val) {
return gClass->method3(path, val);
}
void pupulateInterface(PluginInterface& iface) {
iface.method1 = method1;
iface.method1 = method2;
iface.method1 = method3;
...
}
I don't have control over that global variable nor on the fact that the interface must be a struct of function pointer.
How can I reduce the boilerplate here? I tried using std::bind but it didn't work: a std::function cannot be converted to a C function pointer.
void pupulateInterface2(PluginInterface& iface) {
iface.method1 = [](bool enabled){
gClass->method1(enabled);
};
iface.method2 = [](int param1, int param2){
gClass->method2(param1,param2);
};
iface.method3 = [](const char *path, const int& val){
return gClass->method3(path, val);
};
}

Get address of const method

I would like to be able to form a pointer-to-member type knowing only the class itself and method name. Unfortunately I am not able to do so having a const and non-const method variants in my class.
Example code snippet:
struct A
{
void method() {}
void method() const {}
};
int main()
{
decltype(&A::method) _;
}
I have also tried the following this but without much success either:
decltype(&(std::declval<const A>().method)) _;
Both approaches fail as decltype cannot resolve this due to ambiguity:
'decltype cannot resolve address of overloaded function'
How can I achieve this in some other way?
You can do it like this:
struct A
{
void method() {
cout << "Non const\n";
}
void method() const {
cout << "const function\n";
}
};
int main()
{
typedef void (A::*method_const)() const;
method_const a = &A::method; //address of const method
typedef void (A::*method_nonconst)();
method_nonconst b = &A::method; //address of non const method
A var;
std::invoke(a, var);
std::invoke(b, var);
}
If you want to use decltype() to achieve the same thing, you first have to manually select the function you want using static_cast<>:
int main()
{
//const
decltype( static_cast <void (A::*)() const> (&A::method) ) a;
//non const
decltype( static_cast <void (A::*)()> (&A::method) ) b;
a = &A::method;
b = &A::method;
A var;
std::invoke(a, var);
std::invoke(b, var);
}
Live on Coliru

How can I avoid this code duplication?

I have two methods which have almost the same code except for two methods they call (and some other details I can easily parameterize). However, those method calls have the same signature, so I think I can generalize them into a single method.
class A{
IApi* m_pApi;
void M1();
void M2();
public:
void DoThings();
}
void A::M1(){
int i;
bool b;
m_pApi->method1( &i, &b );
//Other stuff...
}
void A::M2(){
int i;
bool b;
m_pApi->method2( &i, &b );
//Other stuff...
}
void A::DoThings(){
M1();
M2();
}
I can figure out how to "parameterize" the "Other stuff" code, but the problem are the calls to method1 and method2. I think I have to use std::bind somehow, but I can't do something like this...
void A::M( std::function<void(int*,bool*)> f ){
int i;
bool b;
f( &i, &b );
}
void A::DoThings(){
M( std::bind( ???, m_pApi ) ); //M1
M( std::bind( ???, m_pApi ) ); //M2
}
The problem here is that m_pApi is not a concrete class (it's an interface implemented by a bunch of concrete classes), so I'm not sure if I can do the usual &Class::Method thing. Suggestions?
Use pointers to member function.
#include <iostream>
using namespace std;
struct IApi {
void method1(int * i, bool * b) {
*i = 1; *b = true;
}
void method2(int * i, bool * b) {
*i = 2; *b = false;
}
};
class A {
IApi* m_pApi;
void M(void (IApi::*)(int*, bool*));
public:
A() : m_pApi(new IApi()) {}
void DoThings();
};
void A::M(void (IApi::*mptr)(int*, bool*)) {
int i;
bool b;
(m_pApi->*mptr)( &i, &b );
cout << i << ' ' << b << endl;
}
void A::DoThings(){
M(&IApi::method1);
M(&IApi::method2);
}
int main() {
A a;
a.DoThings();
}

C++ template design with function pointers

Im bit new to c++, please let me describe my problem. I have a class called CSubcriber, which main purpose is to execute some callback function, of some type and some number of arguments. For example callbacks can be:
typedef void (*cb1)(void)
typedef int (*cb2)(int, int)
typedef char (*cb3)(int, int, void);
class itself is:
template <class CallbackType>
class CSubscriber {
public:
CSubscriber();
virtual ~CSubscriber();
CallbackType (*m_callback_newWay)(void *params);
void (*m_callback)(void *params);
int (*m_callback_int)(void *params);
void *m_cb_params;
int execute_cb();
void *m_params;
CSubscriber(void (*callback)(void *params), void *cb_params);
CSubscriber(int (*callback)(void *params), void *cb_params);
};
CSubscriber::CSubscriber(void (*callback)(void *params), void *cb_params){
m_callback = callback;
m_cb_params = cb_params;
}
CSubscriber::CSubscriber(int (*callback)(void *params), void *cb_params){
m_callback_int = callback;
m_cb_params = cb_params;
}
My main problem is now, how to write constructor, which will handle with all that variable arguments to callback. After constructing object in some particular moment, callback may be fired, for example:
typedef int (*callback)(void *params);
CSubscriber s(callback, params);
or
typedef void (*callback2)(void *params, int arr, char *ptr);
CSubscriber s(callback, params, arr, ptr);
Now, calling
s->m_callback()
I want to execute callback with all arguments which i passed for constructor.
I'd like to avoid writing ten different constructors, for each different number of arguments passed to callback function. Is it possible to do ?
Try something like this.
#include <iostream>
using namespace std;
typedef void (*cb1)(void);
typedef int (*cb2)(int, int);
typedef char (*cb3)(int, int, char);
template <class CallbackType>
class CSubscriber
{
public:
CSubscriber(): fcn1(0), fcn2(0), fcn3(0) {};
virtual ~CSubscriber(){};
CSubscriber(cb1 fcn): fcn1(fcn), fcn2(0), fcn3(0), a(), b() {};
CSubscriber(cb2 fcn, int p1, int p2): fcn1(0), fcn2(fcn), fcn3(0), a(p1), b(p2) {};
int execute_cb() {
if ( fcn1 != 0 ) {
(*fcn1)();
}
if ( fcn2 != 0 ) {
(*fcn2)(a,b);
}
};
protected:
cb1 fcn1;
cb2 fcn2;
cb3 fcn3;
int a, b;
};
void fcn1() {
cout << "in fcn1" << endl;
};
int fcn2(int a, int b) {
cout << "in fcn2, a " << a << ", b " << b << endl;
};
int main()
{
CSubscriber<int> cs;
CSubscriber<int> cs1(&fcn1);
CSubscriber<int> cs2(&fcn2, 1, 100);
cs.execute_cb();
cs1.execute_cb();
cs2.execute_cb();
}

ARG! Contravarience foils callback plot! Want to change virtual return type

I am working on a AI dynamic link library. It is to be explicitly linked and all of this is handled by a simple header include.
I am at the moment trying to create the code for the DLL to be able to call functions in the main EXE to manipulate the world and also to be able to query functions to learn about the state of the world. I am now at the point where I can call void return functions (be they global functions or member functions) with no parameters.
I am now trying to implement the ability to call functions in the EXE and get the return value from them. (non-void functions) Things are not going well.. I've been trying for a while now trying to find the best way to implement this. I can use boost libraries in the DLL but not in the EXE.
I'm going to do a dump of the relavent code here. I know it is alot but I hope someone will be able to point out how I can improve.
Even if you do not read the code (very understandable) it would be very helpful to know how you would go about tackling this problem in general terms.
Here goes (I've tried to cut out as many unrelated sections of code as I can):
---------------------------------------EXE side header--------------------------------------
typedef void (*Command)();
typedef void (*CommandMF)(int, std::string);
typedef void (*AddEntityFunction)(int&);
typedef void (*AddActionToEntityFunction)(int, Command);
typedef void (*AddActionToEntityFunctionMF)(int, CommandMF, std::string);
typedef void (*UpdateDoubleThinkFunction)();
class MemberFunctionStorageExecute
{
public:
virtual void Execute() const =0;
};
template <class T>
struct MemberFunctionStorage : MemberFunctionStorageExecute
{
typedef void (T::*MemberFunctionWorker)();
MemberFunctionWorker mbw;
T *obj;
virtual void Execute() const
{
(obj->*mbw)();
}
};
typedef std::map<std::string, MemberFunctionStorageExecute*> MemberFunctionsList;
typedef std::map<int, MemberFunctionsList*> ListofLists;
//Template hack to allow static properties inside header
template <class T>
class DoubleThinkInterfaceImpl
{
protected:
static HINSTANCE hinstDLL;
static AddEntityFunction DLLAddEntity;
static AddActionToEntityFunction DLLAddActionToEntity;
static AddActionToEntityFunctionMF DLLAddActionToEntityMF;
static UpdateDoubleThinkFunction DLLUpdateDoubleThink;
static ListofLists m_plistlist;
};
template <class T>
HINSTANCE DoubleThinkInterfaceImpl<T>::hinstDLL;
template <class T>
AddEntityFunction DoubleThinkInterfaceImpl<T>::DLLAddEntity;
template <class T>
UpdateDoubleThinkFunction DoubleThinkInterfaceImpl<T>::DLLUpdateDoubleThink;
template <class T>
AddActionToEntityFunction DoubleThinkInterfaceImpl<T>::DLLAddActionToEntity;
template <class T>
AddActionToEntityFunctionMF DoubleThinkInterfaceImpl<T>::DLLAddActionToEntityMF;
template <class T>
ListofLists DoubleThinkInterfaceImpl<T>::m_plistlist;
class DoubleThinkInterface : protected DoubleThinkInterfaceImpl<int>
{
private:
int m_pid;
MemberFunctionsList m_pmemfunlist;
public:
int ID()
{
return m_pid;
}
DoubleThinkInterface()
{
if(!hinstDLL)
{
hinstDLL = LoadLibrary("DoubleThink.dll");
DLLAddEntity = (AddEntityFunction)GetProcAddress(hinstDLL, "AddEntity");
DLLUpdateDoubleThink = (UpdateDoubleThinkFunction)GetProcAddress(hinstDLL, "Update");
DLLAddActionToEntity = (AddActionToEntityFunction)GetProcAddress(hinstDLL, "AddActionToEntity");
DLLAddActionToEntityMF = (AddActionToEntityFunctionMF)GetProcAddress(hinstDLL, "AddActionToEntityMF");
}
DLLAddEntity(m_pid);
DoubleThinkInterface::m_plistlist.insert(std::pair<int, MemberFunctionsList*>(m_pid, &m_pmemfunlist));
}
~DoubleThinkInterface()
{
//if(hinstDLL != 0)
// FreeLibrary(hinstDLL);
}
void AddAction(Command action)
{
DLLAddActionToEntity(m_pid, action);
}
void Update()
{
DLLUpdateDoubleThink();
}
template <class T>
void AddActionMF(T *object, void (T::*memberfunc)(), std::string actionName)
{
MemberFunctionStorage<T> *store = new MemberFunctionStorage<T>;
store->mbw = memberfunc;
store->obj = object;
m_pmemfunlist.insert(std::pair<std::string, MemberFunctionStorageExecute*>(actionName, store));
DLLAddActionToEntityMF(m_pid, &DoubleThinkInterface::ResolveMF, actionName);
}
static void ResolveMF(int idnum,std::string mfName)
{
ListofLists::iterator lit;
lit = m_plistlist.find(idnum);
MemberFunctionsList::iterator it;
it = lit->second->find(mfName);
it->second->Execute();
}
};
-------------------------------EXE-side example------------------------------------
class BaseEntity
{
public:
DoubleThinkInterface dtInterface;
BaseEntity(){}
virtual ~BaseEntity(){}
};
class Humanoid : public BaseEntity
{
public:
Humanoid(){}
~Humanoid(){}
std::string name;
void Move();
int GetAge(){return 10;}
};
void Humanoid::Move()
{
std::cout << name << ": I'm moving around and such \n";
}
void EndLifeAsWeKnowIt()
{
cout << "Suddenly everything changed... \n";
}
int _tmain(int argc, _TCHAR* argv[])
{
Humanoid *entity = new Humanoid();
entity->name = "Bobby";
entity->dtInterface.AddAction(&EndLifeAsWeKnowIt);
entity->dtInterface.AddActionMF<Humanoid>(entity, &Humanoid::Move, "Move");
entity->dtInterface.Update();
int x; cin >> x;
return 0;
}
-------------------------DLL-side code------------------------------------
DTEntityManager* DTEntityManager::Instance()
{
static DTEntityManager instance;
return &instance;
}
template<class T>
void AddAction(int id, void (*comm)(int, std::string), std::string mfid)
{
DTEntity *ent = DTEntityManager::Instance()->GetEntityFromID(id);
CommandMemberFunction<T> *newcomm = new CommandMemberFunction<T>();
newcomm->comm = comm;
newcomm->entityid = id;
newcomm->mfid = mfid;
ent->SetCommandMF(newcomm);
}
extern "C"
{
DLL_EXPORT void AddEntity(int &idnumber)
{
DTEntity *entity = new DTEntity();
idnumber = entity->ID();
DTEntityManager::Instance()->RegisterEntity(entity);
}
DLL_EXPORT void AddActionToEntity(int id, void (*comm)())
{
DTEntity *ent = DTEntityManager::Instance()->GetEntityFromID(id);
CommandGlobal<void> *newcomm = new CommandGlobal<void>();
newcomm->comm = comm;
ent->SetCommand(newcomm);
}
DLL_EXPORT void AddActionToEntityMF(int id, void (*comm)(int, std::string), std::string mfid)
{
AddAction<void>(id, comm, mfid);
}
DLL_EXPORT void AddActionToEntityMF_int(int id, void (*comm)(int, std::string), std::string mfid)
{
AddAction<int>(id, comm, mfid);
}
}
--------------------------DLL-side Structure for holding callbacks ---------------------------
class CommandBase
{
public:
virtual void Execute() const =0;
};
template<class T>
struct CommandGlobal : CommandBase
{
typedef boost::function<T ()> Command;
Command comm;
virtual T Execute() const
{
return comm();
}
};
template<class T>
struct CommandMemberFunction : CommandBase
{
typedef boost::function<T (int, std::string)> Command;
Command comm;
int entityid;
std::string mfid;
virtual T Execute() const
{
return comm(entityid, mfid);
}
};
At the moment the DLL doesn't compile because of this line:
AddAction<int>(id, comm, mfid);
Because it tries to override
virtual void Execute() const =0;
with a function which returns int. Gives non-covariance error.. I know I have been barking up the wrong tree but I can't see any other solution at the moment either.
Does anyone have any advice on how to do it better? Even if it just a vague direction I should direct my attention in I would appreciate it. Thanks a lot if you bother to read all this!
I think you are complicating too much. See this:
/*************** both ***************/
typedef void (*Prototype1)();
typedef void (*Prototype2)(int);
typedef int (*Prototype3)();
struct FuncList {
Prototype3 func1;
Prototype1 func2;
Prototype1 func3;
Prototype2 func4;
Prototype1 func5;
// ...
};
/*************** dll ***************/
FuncList func_list;
Prototype3 &func1 = func_list.func1;
Prototype1 &func2 = func_list.func2;
Prototype1 &func3 = func_list.func3;
Prototype2 &func4 = func_list.func4;
Prototype1 &func5 = func_list.func5;
/* DLLEXPORT */ void SetFuncList(const FuncList &list) { func_list = list; }
void UsageExample()
{
/* Just call the function */
func2();
}
/*************** exe ***************/
/* declarations (functions must be defined somewhere) */
int func1();
void func2();
void func3();
void func4(int);
void func5();
const FuncList func_list = {
func1,
func2,
func3,
func4,
func5
};
typedef void (*SetFuncListProc)(const FuncList &list);
SetFuncListProc SetFuncList;
void Init()
{
/* ... load the DLL, load "SetFuncList" ... */
SetFuncList(func_list);
}
Quick & dirty answer: pass to Execute a reference to the result type as a void*, and make Execute private. Then wrap Execute in a non-virtual wrapper which returns T by value and does the cast.