我维护了一个Arduino库,它使用下面的代码(简化)来打印通过红外线接收到的结果。
unsigned long long decodedData; // for 8 and 16 bit cores it is unsigned long decodedData;
Print MySerial;
MySerial.print(decodedData, 16);
大多数32位arduino内核都提供了size_t Print::print(unsigned long long n, int base)
函数,并且编译时没有错误。
但是有32位内核,它们不提供size_t Print::print(unsigned long long n, int base)
,它们只提供size_t Print::print(unsigned long n, int base)
,在那里我得到了预期的编译时错误call of overloaded 'print(decodedData, int)' is ambiguous
。
我试着理解Check if a class has a member function of a given signature,但还是没有头绪。
我要用
MySerial.print((uint32_t)(decodedData >> 32), 16);
MySerial.print((uint32_t)decodedData & 0xFFFFFFFF, 16);
如果没有提供函数size_t Print::print(unsigned long long n, int base)
。
我试过了
template<typename T>
struct has_uint64_print {
template<typename U, size_t (U::*)(unsigned long long, int)> struct SFINAE {
};
template<typename U> static char test(SFINAE<U, &U::print>*);
template<typename U>
static int test(...);
static const bool has64BitPrint = sizeof(test<T>(nullptr)) == sizeof(char);
};
而这是可行的(感谢雷米勒博):-)。
但此检查不起作用,因为它仍然引用long long print函数(更新:而使用if constexpr ()
(并非对所有内核都可用)也没有帮助)。
if(has_uint64_print<Print>::has64BitPrint){
MySerial.print(decodedData, 16);
} else {
MySerial.print((uint32_t)(decodedData >> 32), 16);
MySerial.print((uint32_t)decodedData & 0xFFFFFFFF, 16);
}
有没有可能避免这个编译错误?
顺便说一句,我不想用2个32位打印来代替所有64位打印,只想用一个很少使用和懒惰的32位核心,因为所有的主流核心都能很好地使用64位打印。
2条答案
按热度按时间vmpqdwk31#
使用C++11,您可以执行以下操作:
第二个版本,具有函式多载和标准型别:
fkvaft9z2#
问题是文档太少。我找到了this,但它没有提供
Serial::print
重载的定义。我猜想它看起来是这样的:
所以当你在
unsigned long long
上使用这个时,你期望它与uint64_t
匹配重载,但是在某些平台上uint64_t
不是unsigned long long
,而是unsigned long
。这种不匹配导致重载解析无法决定使用哪个回退并报告错误:call of overloaded 'print(decodedData, int)' is ambiguous
.因此,与其用“避免调用函数”来使你的生活复杂化,不如显式地使用类型
uint64_t
来修复你的代码。注意,这个类型定义解释了你的意图,所以你应该明确地使用它。如果我错了,请提供更好的链接到这个API文档。也包括完整的错误日志时,建立失败,所以我们可以看到什么重载是可用的。