我正在制作协议界面。该协议应该用于从设备发送ADC数据。各种微控制器具有允许ADC读取的库,但当然,它们是不同的类型。
例如,Nucleo中的模拟阅读:
AnalogIn ain(A0);
unsigned short value = ain.read_u16();
和Arduino:
int analogPin = 3;
int val = analogRead(analogPin);
虽然这种方法返回不同类型并且实际上是完全不同的类型,但它们返回相同的数据。
我的问题是,是否可以创建一个接受这两个函数作为回调的类,并将其返回值返回为int
。
像这样:
class ThisIsNotReal {
public:
ThisIsNotReal(<ANY TYPE THAT CAN CONVERT TO INT HERE> (*cb)() ) {
callback = cb;
}
int getVal() {
return callback();
}
private:
<ANY TYPE ... (some super magical template? anyone?)> (*cb)()
}
当然,我的目标是在不编写太多代码的情况下使用Arduino兼容代码。另外,我想学习一些模板魔术。
答案 0 :(得分:1)
似乎std::function
和lambda可能会有所帮助,例如:
AnalogIn ain(A0);
std::function<int()> AdcRead = [ain](){ return ain.read_u16(); };
和
const int analogPin = 3;
std::function<int()> AdcRead = [analogPin](){ return analogRead(analogPin); };
答案 1 :(得分:1)
除非你为使用回调的所有目标设备配备了C ++ 11编译器,否则不一定非常简单。这是因为调用各种函数所需的存储要求和参数之间存在差异。因为如果这样,您可以考虑创建一个用于从IO端口读取输入的公共接口,然后为每个目标设备/平台提供唯一的实现。这将允许您具有初始化IO相关对象以及从IO端口读取的常用方法。
即使你的目标平台上有一个C ++ 11编译器,如果它们被证明会影响性能,那么使用std::function
或virtual
函数可能也不可取(或者甚至是一个选项)。类似下面的代码可能更加可行,因为它很简单。
#if defined (IS_NUCLEO)
struct InputDevice
{
InputDevice(int port) : device(port) {}
int read() const
{
return static_cast<int>(device.read_u16());
}
AnalogIn device;
};
#endif
#if defined(IS_ARDUINO)
struct InputDevice
{
InputDevice(int port) : port(port) {}
int read() const { return analogRead(port); }
int port;
};
#endif
我建议你定制它以满足你的确切要求。
答案 2 :(得分:0)
ThisIsNotReal
应存储ConvertFuncToIntBase* conv
类型的指针并调用conv->getVal()
。您将通过在makeIntConverter
的构造函数中调用ThisIsNotReal
来创建适当的实例。 makeIntConverter
如果传递给它的函数的返回类型不能转换为int
,则不会编译。虽然下面的解决方案使用需要C ++ 11的std::enable_if
和std::is_convertible
,但您可以使用类似的C ++ 03 Boost方法。
class ConvertFuncToIntBase
{
public:
virtual int getVal() = 0;
virtual ~ConvertFuncToIntBase(){}
};
template <typename T>
class ConvertFuncToInt : ConvertFuncToIntBase
{
public:
ConvertFuncToIntLand(T (*cb)()) : callback(cb)
{
}
int getVal()
{
return (int)callback();
}
private:
T (*callback)();
};
template <typename T, typename = typename std::enable_if<std::is_convertible<T, int>>::type>
std::unique_ptr<ConvertFuncToIntBase> makeIntConverter(T (*cb)())
{
return std::unique_ptr<ConvertFuncToIntBase>(new ConvertFuncToInt<T>(cb));
}