根据我为变量选择的类型,我遇到了以下错误。
/home/zak/Development/Arduino/generated_examples/ArduinoIoTCloud_Basic/thingProperties.h: In function 'void initProperties()':
/home/zak/Development/Arduino/libraries/ArduinoIoTCloud/src/ArduinoIoTCloud.h:116:64: error: cannot bind non-const lvalue reference of type 'int16_t& {aka int&}' to an rvalue of type 'int16_t {aka int}'
#define addProperty( v, ...) addPropertyReal(v, #v, __VA_ARGS__)
^
/home/zak/Development/Arduino/generated_examples/ArduinoIoTCloud_Basic/thingProperties.h:32:16: note: in expansion of macro 'addProperty'
ArduinoCloud.addProperty(potentiometer, 2, Permission::Read).publishOnChange(10);
^
In file included from /home/zak/Development/Arduino/generated_examples/ArduinoIoTCloud_Basic/ArduinoIoTCloud_Basic.ino:17:0:
/home/zak/Development/Arduino/libraries/ArduinoIoTCloud/src/ArduinoIoTCloud.h:158:15: note: initializing argument 1 of 'Property& ArduinoIoTCloudClass::addPropertyReal(int16_t&, String, int, Permission)'
Property& addPropertyReal(int16_t& property, String name, int tag, Permission const permission);
^~~~~~~~~~~~~~~
这是
addPropertyReal()
的正文:
Property& ArduinoIoTCloudClass::addPropertyReal(int16_t& property, String name, int tag, Permission const permission)
{
Property* p = new CloudWrapperInt16(property);
return addPropertyReal(*p, name, tag, permission);
}
问题发生在
new
ing CloudWrapperInt16
时:
class CloudWrapperInt16 : public CloudWrapperBase {
private:
int16_t &_primitive_value,
_cloud_value,
_local_value;
public:
CloudWrapperInt16(int16_t& v) : _primitive_value(v), _cloud_value(v), _local_value(v) {}
...
^^ 如您所见,
_primitive_value
是参考。
奇怪的是,当我通过实际的
int
或 int16_t
时,这会起作用。但是,每当我传入一个等效但必须转换为 int16_t
的值(例如 short
)时,我都会遇到此错误。
成功(
int16_t
):(编译时没有警告)
int16_t potentiometer;
...
void initProperties() {
...
ArduinoCloud.addProperty(potentiometer, Permission::Read).publishOnChange(10);
成功(
int
):(编译时没有警告)
int potentiometer;
...
void initProperties() {
...
ArduinoCloud.addProperty(potentiometer, Permission::Read).publishOnChange(10);
失败 (
short
): (错误如上所示)
short potentiometer;
...
void initProperties() {
...
ArduinoCloud.addProperty(potentiometer, Permission::Read).publishOnChange(10);
编辑: 最初,我忘记提及这个特定示例是针对 16 位平台进行编译的。所以
、int
和short
的大小应该相同。int16_t
在一个非常奇怪的转折中,当我通过
short
或 int16_t
时,这会起作用。但是,每当我传入 int
值时,我都会遇到类似的错误。
成功(
int16_t
):(编译时没有警告)
int16_t potentiometer;
...
void initProperties() {
...
ArduinoCloud.addProperty(potentiometer, Permission::Read).publishOnChange(10);
成功(
short
):(编译时没有警告)
short potentiometer;
...
void initProperties() {
...
ArduinoCloud.addProperty(potentiometer, Permission::Read).publishOnChange(10);
FAIL (
int
): (类似错误如上所示)
int potentiometer;
...
void initProperties() {
...
ArduinoCloud.addProperty(potentiometer, Permission::Read).publishOnChange(10);
有人可以解释一下类型转换到底发生了什么吗?
我正在寻找一种符合 POSIX 标准的方法,以便编译器同等对待它们,或者一种增强代码以允许其工作的方法。任何解决方案都需要针对多种架构(16 位、32 位等)进行编译,并且需要在多个工具链上工作(
avr-gcc
、arm-none-eabi-g++
等)。
注意:我无法控制代码库;这是一个大型开源项目。我真的需要一个外科手术解决方案,因为重构工作越广泛,PR 被接受就越难。
注意:这个答案欢迎改进,仅作为其他人的面包屑。它基于经验观察,而不是深入研究相关编译器的源代码或研究 ISO。
看起来
avr-gcc
编译器别名 int16_t
为 int
(反之亦然),并且 short
是单独定义的。而 arm-none-eabi-gcc
编译器别名 int16_t
为 short
(反之亦然)。
成功可以归因于它们实际上是相同的数据类型,因此不需要强制转换或转换。因此,失败源于编译器认为有必要进行转换或强制转换的事实。
一旦发生强制转换,就会创建一个临时对象。显然,临时对象不能绑定到非常量引用(这使得错误消息有意义),因为该引用没有与其关联的存储,因此无法在运行时修改。
如果您很难概念化这一点,请考虑从整数到浮点数的转换。不可能通过修改浮点值来更新基础整数。
就我而言,我需要的解决方案是进一步模板化基于整数的类和函数。这最终抽象了单个通用实现背后的所有整数运算。