Подтвердить что ты не робот

Сопоставление нескольких типов для разрешения специализации шаблона

Кратко отвергните тот факт, что нормальная перегрузка функций будет служить этому примеру лучше. Это подразумевается только как способ узнать о программировании шаблонов. Сказав это, вы можете прокомментировать преимущества/различия, которые вы получите от использования перегрузки функций, по сравнению с специализированной функцией шаблона (хотя это может заслуживать самого себя).


Рассмотрим следующий пример:

template <typename T>
inline void ToString(T value, char* target, size_t max_size );

template <>
inline void ToString<float>(float value, char* target, size_t max_size)
{
   snprintf( target , max_size , "%f" , value);
}

template <>
inline void ToString<double>(double value, char* target, size_t max_size)
{
    snprintf( target , max_size , "%f" , value);
}

Есть ли способ написать только одну из этих специализаций, которые соответствуют типам float и double?

В принципе, я предвижу писать специализацию шаблона для типа шаблона, которая будет соответствовать как float, так и double (как тип совпадения типа "float или double" ), но я не уверен, что это вообще возможно С++. Тем не менее, я видел, что перед моими глазами случается неожиданная магия шаблона, поэтому я думаю, что здесь есть хороший вопрос.

4b9b3361

Ответ 1

Здесь стандартная идиома решения:

#include <type_traits>
#include <cstdio>


// Helper class

template <typename T>
struct Printer
{
  static typename std::enable_if<std::is_floating_point<T>::value, int>::type
  print(T x, char * out, std::size_t n)
  {
    return std::snprintf(out, n, "%f", x);
  }
};

// Convenience function wrapper

template <typename T> int print(T x, char * out, std::size_t n)
{
  return Printer<T>::print(x, out, n);
}

void f()
{
  char a[10];

  Printer<double>::print(1.2, a, 10);  // use helper class
  print(1.4f, a, 10);                  // wrapper deduces type for you
}

Вы получите ошибку времени компиляции, если вы вызываете либо конструкцию с неплавающим типом. Остерегайтесь, хотя это может ошибочно работать для длинных удвоений, для которых требуется спецификатор формата %Lf; и также помните, что float получает повышение до удвоения при передаче через аргументы вариационной функции.