Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

match multiple types for template specialization resolution

Briefly dismiss the fact that normal function overloading will serve this example better. It is meant only as a way to learn about template programming. Having said that, you are welcome to comment on the benefits/differences you'll get from using function overload, compared to function template specialization (although that might deserve a question of its own).


Consider the following example:

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);
}

Is there a way to write only one of these specializations that match both float and double types?

Basically I envision writing a template specialization for a template type that will match both float and double (as sort of 'float or double' type matcher) but I'm not sure whether that is possible at all with C++. That said, I've seen unexpected template magic happen in front of my eyes before, so I think it's a good question to ask here.

like image 503
lurscher Avatar asked Sep 02 '11 15:09

lurscher


1 Answers

Here's a standard solution idiom:

#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
}

You'll get a compile-time error if you call either construction with a non-floating type. Beware though that this might erroneously work for long doubles, which require the %Lf format specifier; and also recall that floats get promoted to doubles when passed through variadic function arguments.

like image 87
Kerrek SB Avatar answered Oct 12 '22 14:10

Kerrek SB