C++ 是否可以只使用函数成员属性创建回调接口?
上下文:C++ 是否可以只使用函数成员属性创建回调接口?,c++,templates,interface,callback,embedded,C++,Templates,Interface,Callback,Embedded,上下文: 不使用堆的嵌入式C++。 我想掌握我的代码(包括它的大小),所以我不想使用标准库,比如std::function 第一次进近: 让我们以这个示例(这是我的代码的简化版本)为例,使用以下的修改版本: 注意:我的回调方法可以有以下两个签名:bool(ChildCrtp::*)(void)和无效(ChildCrtp::*)(int)(一个用于操作,一个用于条件) 因为不可能接受临时对象的地址,这在C++中是不合法的。 此回调接口的问题在于它需要一个指针来存储对象“FooGenericCall
不使用堆的嵌入式C++。 我想掌握我的代码(包括它的大小),所以我不想使用标准库,比如std::function
第一次进近: 让我们以这个示例(这是我的代码的简化版本)为例,使用以下的修改版本: 注意:我的回调方法可以有以下两个签名:bool(ChildCrtp::*)(void)代码>和无效(ChildCrtp::*)(int)
(一个用于操作,一个用于条件)
因为不可能接受临时对象的地址,这在C++中是不合法的。
此回调接口的问题在于它需要一个指针来存储对象“FooGenericCallback”,该对象不能是“FooSpecificCallback”,因为对象类型在母类中未知
3)实现回调作为接口的其他方法
但解决方案仍然使用对象将函数成员存储在接口(或接口的子级)中
4)Lambdas…
我知道lambdas会简化我的生活,事实上,我首先使用lambdas,代码大小从60kB增加到120kB(!),这是因为lambdas的存储方式:在std::function中。答案不是“lambda”吗?)我仍然不确定我是否正确理解了你的意图。但是下面的代码编译没有错误,尽管我没有进一步测试:
template<typename ChildCrtp>
class MotherInterface
{
protected:
//Callback types
using SomethingBooleanCallback = bool (ChildCrtp::*)();
protected:
//Helper methods
bool AlwaysTrue(void) { return true; };
SomethingBooleanCallback callback;
public:
void UseCallback(SomethingBooleanCallback a) {callback = a;}
bool CallCallback() {return ((ChildCrtp *)this->*callback)();}
};
template<typename ChildCrtp>
class SpecializedInterfaceA : public MotherInterface<ChildCrtp>
{
public:
/// methods to be overridden in child methods where the callbacks need to be bound
virtual int GetValue (void) const = 0;
protected:
///another helper methods
bool IsPositive(void) { return (GetValue() > 0); };
bool IsNegative(void) { return (GetValue() < 0); };
bool IsEven(void) { return ((GetValue() % 2) == 0); };
bool IsOdd(void) { return ((GetValue() % 2) == 1); };
};
template<typename ChildCrtp>
class ChildA1 : public SpecializedInterfaceA<ChildCrtp>
{
public:
//implements the interface
virtual int GetValue (void) const final override { return value;} ;
//bind the interfaces' callback by a reference to the object "isPositive", which contains a pointer to the desired method and a pointer to the object that owns the method)
void BindPositive(void) { this->UseCallback(&ChildA1::IsPositive); };
private:
//an attribute
int value;
};
模板
类接口
{
受保护的:
//回调类型
使用SomethingBooleanCallback=bool(ChildCrtp::*)();
受保护的:
//辅助方法
bool AlwaysTrue(void){返回true;};
布尔回调;
公众:
void UseCallback(SomethingBooleanCallback a){callback=a;}
bool CallCallback(){return((ChildCrtp*)this->*callback)(;}
};
模板
类SpecializedInterfaceA:公共母机接口
{
公众:
///在需要绑定回调的子方法中重写的方法
虚拟int GetValue(void)const=0;
受保护的:
///另一种辅助方法
bool IsPositive(void){return(GetValue()>0);};
bool为负(void){return(GetValue()<0);};
bool-IsEven(void){return((GetValue()%2)==0);};
bool IsOdd(void){return((GetValue()%2)=1);};
};
模板
类别1:公共专用接口A
{
公众:
//实现接口
虚int GetValue(void)常量最终重写{return value;};
//通过对对象“isPositive”的引用绑定接口的回调,该对象包含指向所需方法的指针和指向拥有该方法的对象的指针)
void BindPositive(void){this->UseCallback(&ChildA1::IsPositive);};
私人:
//属性
int值;
};
这里是固定版本
#include <iostream>
#include <stdint.h>
using namespace std;
template <typename FunctionType = void, typename... ArgumentType>
class GenericCallback
{
public:
virtual ~GenericCallback(){}
virtual FunctionType Execute(ArgumentType... arg) = 0; //!< execute callback
virtual bool IsValid() const = 0; //!< check if callback is valid
};
template <typename ObjectType, typename FunctionType = void, typename... ArgumentType>
class Callback : public GenericCallback<FunctionType, ArgumentType...>
{
public:
Callback() ://!< Default constructor
pObject_m(0),
pFunction_m(0)
{
}
Callback(ObjectType* pObject_m, FunctionType(ObjectType::*pFunction_m)(ArgumentType...))//!< Constructor
{
this->pObject_m = pObject_m;
this->pFunction_m = pFunction_m;
}
virtual FunctionType Execute(ArgumentType... arg)//!< execute callback implementation
{
return (pObject_m->*pFunction_m)(arg...);
}
virtual bool IsValid(void) const//!< callback validity check implementation
{
return (pObject_m != 0) && (pFunction_m != 0);
}
private:
ObjectType* pObject_m; //!< pointer to object where the callback is defined
FunctionType(ObjectType::* pFunction_m)(ArgumentType...); //!< pointer to the callback (function-member) of the object
};
template<typename ChildCrtp>
class Interface
{
public:
using FooSpecificCallback = Callback<ChildCrtp, bool>;
using FooPrototype = bool(Interface::*)();
template<FooPrototype op>
FooSpecificCallback* checkIf(void)
{
return new FooSpecificCallback(static_cast<ChildCrtp*>(this), op);
}
virtual int getValue(void) = 0;
bool IsNegative() { return (getValue() < 0); };
};
class Mother
{
public:
using FooGenericCallback = GenericCallback<bool>*;
int getValue(){return x_;};
void storeCallback(FooGenericCallback pCallback){pCallback_ = pCallback;};
bool callCallback(){return (pCallback_->IsValid() == false)?:pCallback_->Execute();};
private:
int x_ = 3;
FooGenericCallback pCallback_;
};
class Child : public Mother, public Interface<Child>
{
public:
int getValue(){return Mother::getValue();}
void setup(void){storeCallback(checkIf<&Child::IsNegative>());}
};
int main()
{
Child c;
c.setup();
cout << std::boolalpha << "expectFalse: " << c.callCallback() << endl;
return 0;
}
#包括
#包括
使用名称空间std;
模板
类GenericCallback
{
公众:
虚拟~GenericCallback(){}
虚拟函数类型执行(ArgumentType…arg)=0;/!对象\u m=对象\u m;
此->pFunction\u m=pFunction\u m;
}
虚拟函数类型执行(ArgumentType…arg)/!<执行回调实现
{
返回(pObject_m->*pFunction_m)(arg…);
}
虚拟bool IsValid(void)const/!<回调有效性检查实现
{
返回(pObject_m!=0)和&(pFunction_m!=0);
}
私人:
ObjectType*pObject_m;/!<指向定义回调的对象的指针
FunctionType(ObjectType::*pFunction_m)(ArgumentType…;/!<指向对象回调(函数成员)的指针
};
模板
类接口
{
公众:
使用FooSpecificCallback=Callback;
使用FooPrototype=bool(接口::*)();
模板
FooSpecificCallback*checkIf(无效)
{
返回新的FooSpecificCallback(static_cast(this),op);
}
虚拟int getValue(void)=0;
bool为负(){return(getValue()<0);};
};
班主任
{
公众:
使用FooGenericCallback=GenericCallback*;
int getValue(){return x;};
void-storeCallback(FooGenericCallback-pCallback){pCallback\u=pCallback;};
bool callCallback(){return(pCallback->IsValid()==false)?:pCallback->Execute();};
私人:
int x_uu=3;
FooGenericCallback pcCallback;
};
类子级:公共母级,公共接口
{
公众:
int getValue(){return Mother::getValue();}
无效设置(void){storeCallback(checkIf());}
};
int main()
{
儿童c;
c、 设置();
cout我可能过分简化了您的需求,但有什么问题:
模板
类接口:公共基
{
公众:
静态bool为负(Base*userData)
{
auto-that=static_cast(userData);
返回->getValue()<0;
}
};
班主任
{
公众:
使用Callback=bool(*)(母亲*);
int getValue(){return x_;}
void-storeCallback(Callback-pCallback){pCallback\u=pCallback;}
bool callCallback(){return pCallback_?(*pCallback_?)(this):throw 42;}
私人:
int x_uu=3;
回调pccallback;
};
类子级:公共接口
{
公众:
void setup(){storeCallback(&Interface::IsNegative);}
};
int main()
{
儿童c;
c、 设置();
std::cout此解决方案受Jarod42答案的启发,编译并运行
将MotherA的属性x
更改为null
,负值
和正值
,并检查结果
#include <iostream>
#include <stdint.h>
using namespace std;
static constexpr int STORE_SIZE = 4;
void* operator new(size_t size)
{
cout << "ERROR HEAP USED" << endl;
}
template<typename T, size_t storeSize>
class CallbackStore
{
public:
CallbackStore() : that_(nullptr) {};
CallbackStore(T* that) : that_(that) {};
using CallbackCondition = bool (*) (T*);
using CallbackAction = void (*) (T*,int);
struct Step
{
CallbackCondition pCallbackCondition;
CallbackAction pCallbackAction;
};
void setStep(int stepId,CallbackCondition pCallbackCondition, CallbackAction pCallbackAction)
{
if(stepId<storeSize)
{
store[stepId].pCallbackCondition = pCallbackCondition;
store[stepId].pCallbackAction = pCallbackAction;
}
else
{
cout << "pointer error" << endl;
}
}
void callStep(int stepId, int param)
{
if((stepId<storeSize) &&
(store[stepId].pCallbackCondition != nullptr) &&
(store[stepId].pCallbackAction != nullptr) &&
(that_ != nullptr))
{
bool isActive = (*(store[stepId].pCallbackCondition))(that_);
if(isActive) {(*(store[stepId].pCallbackAction))(that_,param);}
}
else
{
cout << "pointer error" << endl;
}
}
Step store[storeSize];
T* that_;
};
template<typename Base>
class Interface : public Base // interface
{
public:
static bool True(Base* baseInstance)
{
return true;
}
static bool IsNegative(Base* baseInstance)
{
return ((static_cast<Base*>(baseInstance))->getValue() < 0);
}
static bool IsNull(Base* baseInstance)
{
return ((static_cast<Base*>(baseInstance))->getValue() == 0);
}
static void PrintValue(Base* baseInstance, int value)
{
cout << "print this value : " << value << "." << endl;
}
};
class MotherA
{
public:
int getValue() { return x_; }
void setValue(int x) { x_ = x; }
private:
int x_ = -3;
};
class ChildA : public Interface<MotherA>, public CallbackStore<MotherA, STORE_SIZE>
{
public:
ChildA():Interface<MotherA>(), CallbackStore<MotherA, STORE_SIZE>(this){};
void setup()
{
setStep(0, &Interface::IsNegative, &Interface::PrintValue );
setStep(1, &Interface::IsNull, &Interface::PrintValue );
setStep(2, &Interface::IsNull, &Interface::PrintValue );
setStep(3, &Interface::True, &Interface::PrintValue );
}
};
int main()
{
ChildA c;
c.setup();
for(int i = 0; i < STORE_SIZE; i++)
{
c.callStep(i,8);
}
// shall print "print this value : 8." 3 times if x_ is null, twice if x_ is negative.
}
#包括
#包括
template<typename ChildCrtp>
class MotherInterface
{
protected:
//Callback types
using SomethingBooleanCallback = bool (ChildCrtp::*)();
protected:
//Helper methods
bool AlwaysTrue(void) { return true; };
SomethingBooleanCallback callback;
public:
void UseCallback(SomethingBooleanCallback a) {callback = a;}
bool CallCallback() {return ((ChildCrtp *)this->*callback)();}
};
template<typename ChildCrtp>
class SpecializedInterfaceA : public MotherInterface<ChildCrtp>
{
public:
/// methods to be overridden in child methods where the callbacks need to be bound
virtual int GetValue (void) const = 0;
protected:
///another helper methods
bool IsPositive(void) { return (GetValue() > 0); };
bool IsNegative(void) { return (GetValue() < 0); };
bool IsEven(void) { return ((GetValue() % 2) == 0); };
bool IsOdd(void) { return ((GetValue() % 2) == 1); };
};
template<typename ChildCrtp>
class ChildA1 : public SpecializedInterfaceA<ChildCrtp>
{
public:
//implements the interface
virtual int GetValue (void) const final override { return value;} ;
//bind the interfaces' callback by a reference to the object "isPositive", which contains a pointer to the desired method and a pointer to the object that owns the method)
void BindPositive(void) { this->UseCallback(&ChildA1::IsPositive); };
private:
//an attribute
int value;
};
#include <iostream>
#include <stdint.h>
using namespace std;
template <typename FunctionType = void, typename... ArgumentType>
class GenericCallback
{
public:
virtual ~GenericCallback(){}
virtual FunctionType Execute(ArgumentType... arg) = 0; //!< execute callback
virtual bool IsValid() const = 0; //!< check if callback is valid
};
template <typename ObjectType, typename FunctionType = void, typename... ArgumentType>
class Callback : public GenericCallback<FunctionType, ArgumentType...>
{
public:
Callback() ://!< Default constructor
pObject_m(0),
pFunction_m(0)
{
}
Callback(ObjectType* pObject_m, FunctionType(ObjectType::*pFunction_m)(ArgumentType...))//!< Constructor
{
this->pObject_m = pObject_m;
this->pFunction_m = pFunction_m;
}
virtual FunctionType Execute(ArgumentType... arg)//!< execute callback implementation
{
return (pObject_m->*pFunction_m)(arg...);
}
virtual bool IsValid(void) const//!< callback validity check implementation
{
return (pObject_m != 0) && (pFunction_m != 0);
}
private:
ObjectType* pObject_m; //!< pointer to object where the callback is defined
FunctionType(ObjectType::* pFunction_m)(ArgumentType...); //!< pointer to the callback (function-member) of the object
};
template<typename ChildCrtp>
class Interface
{
public:
using FooSpecificCallback = Callback<ChildCrtp, bool>;
using FooPrototype = bool(Interface::*)();
template<FooPrototype op>
FooSpecificCallback* checkIf(void)
{
return new FooSpecificCallback(static_cast<ChildCrtp*>(this), op);
}
virtual int getValue(void) = 0;
bool IsNegative() { return (getValue() < 0); };
};
class Mother
{
public:
using FooGenericCallback = GenericCallback<bool>*;
int getValue(){return x_;};
void storeCallback(FooGenericCallback pCallback){pCallback_ = pCallback;};
bool callCallback(){return (pCallback_->IsValid() == false)?:pCallback_->Execute();};
private:
int x_ = 3;
FooGenericCallback pCallback_;
};
class Child : public Mother, public Interface<Child>
{
public:
int getValue(){return Mother::getValue();}
void setup(void){storeCallback(checkIf<&Child::IsNegative>());}
};
int main()
{
Child c;
c.setup();
cout << std::boolalpha << "expectFalse: " << c.callCallback() << endl;
return 0;
}
#include <iostream>
#include <stdint.h>
using namespace std;
static constexpr int STORE_SIZE = 4;
void* operator new(size_t size)
{
cout << "ERROR HEAP USED" << endl;
}
template<typename T, size_t storeSize>
class CallbackStore
{
public:
CallbackStore() : that_(nullptr) {};
CallbackStore(T* that) : that_(that) {};
using CallbackCondition = bool (*) (T*);
using CallbackAction = void (*) (T*,int);
struct Step
{
CallbackCondition pCallbackCondition;
CallbackAction pCallbackAction;
};
void setStep(int stepId,CallbackCondition pCallbackCondition, CallbackAction pCallbackAction)
{
if(stepId<storeSize)
{
store[stepId].pCallbackCondition = pCallbackCondition;
store[stepId].pCallbackAction = pCallbackAction;
}
else
{
cout << "pointer error" << endl;
}
}
void callStep(int stepId, int param)
{
if((stepId<storeSize) &&
(store[stepId].pCallbackCondition != nullptr) &&
(store[stepId].pCallbackAction != nullptr) &&
(that_ != nullptr))
{
bool isActive = (*(store[stepId].pCallbackCondition))(that_);
if(isActive) {(*(store[stepId].pCallbackAction))(that_,param);}
}
else
{
cout << "pointer error" << endl;
}
}
Step store[storeSize];
T* that_;
};
template<typename Base>
class Interface : public Base // interface
{
public:
static bool True(Base* baseInstance)
{
return true;
}
static bool IsNegative(Base* baseInstance)
{
return ((static_cast<Base*>(baseInstance))->getValue() < 0);
}
static bool IsNull(Base* baseInstance)
{
return ((static_cast<Base*>(baseInstance))->getValue() == 0);
}
static void PrintValue(Base* baseInstance, int value)
{
cout << "print this value : " << value << "." << endl;
}
};
class MotherA
{
public:
int getValue() { return x_; }
void setValue(int x) { x_ = x; }
private:
int x_ = -3;
};
class ChildA : public Interface<MotherA>, public CallbackStore<MotherA, STORE_SIZE>
{
public:
ChildA():Interface<MotherA>(), CallbackStore<MotherA, STORE_SIZE>(this){};
void setup()
{
setStep(0, &Interface::IsNegative, &Interface::PrintValue );
setStep(1, &Interface::IsNull, &Interface::PrintValue );
setStep(2, &Interface::IsNull, &Interface::PrintValue );
setStep(3, &Interface::True, &Interface::PrintValue );
}
};
int main()
{
ChildA c;
c.setup();
for(int i = 0; i < STORE_SIZE; i++)
{
c.callStep(i,8);
}
// shall print "print this value : 8." 3 times if x_ is null, twice if x_ is negative.
}