c++ - 如何使用模板根据数据类型调用函数?

标签 c++ arduino

我正在开发一个 Arduino 库,如果传递的是 float 而不是整数值,某些方法的行为将有所不同。它必须是这种方式,因为如果传递 float 而不是整数,底层函数必须执行更多数学运算。

这里有一些孤立的、精简的代码来演示这个问题。

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)。我还希望模板函数在传递 float 时调用 printdata(float)(例如 printdata(10.00))。

但是,当我调用 printdata(1000) 时,我的编译器给我一个错误,指出 call of overloaded 'printdata(const double&)' is ambiguous

这可以在不必手动转换所有内容的情况下实现吗?我希望我正在编写的库尽可能对用户友好且不那么冗长。手动转换所有内容对我来说并不是一个很好的解决方案。

谢谢!

最佳答案

考虑 std::is_integral来自 <type_traits> header 和 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 中的任何内容 header ,因为您提到您出于某种原因无法访问它?

注意:我将要展示的代码非常粗俗,我绝不会建议在学术练习或好奇心之外编写它。原因是缺少 type_traits header ,这意味着我们必须定义比我们在其他情况下必须定义的更多的东西,例如SFINAE。此外,大多数模板代码使用大量 type_traits东西,这让事情变得更加尴尬。

所以在这一点上(没有 type_traits header 或 C++17),我建议不要使用模板,只需为您要使用的每种类型重载 printdata with,这避免了模棱两可的重载问题。

// given a type T, defines a static member function called f that routes to the correct form of printdata.
// default implementation goes to int version.
template<typename T> struct _get_version { static void f(T val) { printdata(static_cast<uint32_t>(val)); } };

// specialize this for all the floating point types (float, double, and long double).
template<> struct _get_version<float> { static void f(float val) { printdata(static_cast<float>(val)); } };
template<> struct _get_version<double> { static void f(double val) { printdata(static_cast<float>(val)); } };
template<> struct _get_version<long double> { static void f(long double val) { printdata(static_cast<float>(val)); } };

template<typename Data>
void myTemplate(Data d)
{
    // get the version Data should use, then use its internal f function
    _get_version<Data>::f(d);
}

关于c++ - 如何使用模板根据数据类型调用函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55698382/

相关文章:

c++ - 从工作线程访问共享数据

c++ - static const byte ASCII 错误(可能是错误的实现)

c++ - 软件光栅化实现加速思路

linux - OpenWrt 脚本(无限循环)停止通过串行端口发送数据

mobile - 将 Adob​​e AIR 移动应用程序无线连接到 Arduino - 有哪些选项?

c - Arduino/C : Convert byte array to string or other comparable text format

java - UnsatisfiedLinkError Java 与 Rxtx 库

c++ - 开源项目通常是如何组织和部署的?

c++ - 为什么要使用 "PIMPL"成语?

c++ - 如何应用 C++ 的 ReSharper Ultimate 命名样式