我正在使用Arduino库,如果传递浮点数而不是整数值,则某些方法的行为将有所不同。之所以必须这样,是因为如果传递浮点数而不是整数,则基础函数必须执行更多的数学运算。
这里有一些孤立的,精简的代码来演示问题。
void printdata(uint32_t data)
{
Serial.printf("Printing unsigned integer %d", data);
}
void printdata(float data)
{
Serial.printf("Printing float %i", data);
}
template<typename Data>
void myTemplate(const Data& d)
{
printdata(d);
}
如果传递整数(例如printdata(1000)
),我希望模板函数调用printdata(uint32_t)。我还希望模板函数在传递浮点数(例如printdata(10.00)
)时调用printdata(float)。
但是,当我调用printdata(1000)
时,编译器给我一个错误,提示call of overloaded 'printdata(const double&)' is ambiguous
。
能否无需手动投射所有内容来实现?我希望我正在编写的库对用户友好并且尽可能不冗长。手动投射所有内容对我来说并不是一个很好的解决方案。
谢谢!
答案 0 :(得分:1)
考虑std::is_integral
标头中的<type_traits>
以及C ++ 17 constexpr if
。
std::is_integral
会告诉您在编译时给定类型是否为整数类型。
constexpr if
基本上是一个if语句,在编译时进行评估。未被执行的分支永远不会执行(实际上甚至不会被编译)。
#include <type_traits>
void printdata(uint32_t data)
{
Serial.printf("Printing unsigned integer %d", data);
}
void printdata(float data)
{
Serial.printf("Printing float %i", data);
}
template<typename Data>
void myTemplate(const Data& d)
{
// uses C++17 constexpr if
if constexpr (std::is_integral_v<Data>) printdata(static_cast<uint32_t>(d));
else printdata(static_cast<float>(d));
}
编辑:但是,如果您不能使用C ++ 17,则需要使用更高级的模板逻辑,我将在下面进行演示。我还将避免使用type_traits
标头中的任何内容,因为您提到由于某种原因您无权访问它?
注意:我将要展示的代码非常粗糙,我绝不建议在学术练习或好奇心之外编写代码。这样做的原因是缺少type_traits
标头,这意味着我们必须定义的内容比我们以前要定义的要多得多。 SFINAE。此外,大多数模板代码都使用了大量type_traits
的东西,这使它更加尴尬。
因此,在这一点上(没有type_traits
标头或C ++ 17),我建议不要使用模板,而只是对要使用的每种类型进行重载 {{1 }},从而避免了模棱两可的重载问题。
printdata
答案 1 :(得分:0)
有时我们必须提供其他重载以消除选项之间的歧义。在这种情况下,我们将为printdata
提供其他重载。
最好的选择是只为printdata
,int
和您关心的其他数据类型添加其他double
函数,但是如果可以,请使用{ {1}}和unsigned int
s,您可以直接投放它们。
float