Рассмотрим 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), Я бы предложил не использовать шаблоны и просто делать перегрузки для каждого типа, с которым вы хотите использовать printdata
, с которым устраняет проблему неоднозначных перегрузок.
// 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);
}