C++ Template Function Specialization

Started by
3 comments, last by CoreMeltdown 18 years, 7 months ago
Hi, consider the following sample function:

template <class T1, class T2>
Vec3<T1> Convert(const Vec3<T2> & v) {
  return Vec3(T1(v[0]), T1(v[1]), T1(v[2]));
}

As you can argue, it simply convert from a Vec3 of some type to a Vec3 of another type. Now suppose I want to specialize the template in order to avoid cycle-wasting operations when T1 and T2 are the same (well, the above example is trivial, I think some compiler should be smart enough to optimize...). However, I'd like to code a specialization of the form:

template <class T>
Vec3<T> Convert<T, T>(const Vec3<T> & v) { // <-- here is the "syntax" question
  return v;
}

Does C++ allow such kind of specialization on non-member functions? If it does, what's the right syntax? Thank you :)
Advertisement
You can't partially specialize template functions; however you can do that with inner classes, or structs.

The syntax would be something like:

template <typename T1, typename T2>struct Convert{    Vec3<T1> convert(const Vec3<T2> & v)    {      return Vec3(T1(v[0]), T1(v[1]), T1(v[2]));    }};template <typename T>struct Convert<T,int>{    Vec3<T> convert(const Vec3<int> & v)     {      return v;    }};
my_life:          nop          jmp my_life
[ Keep track of your TDD cycle using "The Death Star" ] [ Verge Video Editor Support Forums ] [ Principles of Verg-o-nomics ] [ "t00t-orials" ]
And you can again put a function template to act as a front-end:

namespace detail{   template <typename T1, typename T2>   struct converter   {      typedef Vec<T1> result_type;      typedef Vec<T2> argument_type;      static result_type convert()(const argument_type& arg)      {         return result_type(T1(arg[0]), T1(arg[1]), T1(arg[2]));      }   };   template <typename T>   struct converter<T,T>   {      typedef Vec<T> result_type;      typedef Vec<T> argument_type;      static result_type convert()(const argument_type& arg)      {         return arg;      }   };}template<class T1, class T2>typename detail::converter<T1,T2>::result_type convert(const T2& arg){   return detail::converter<T1,T2>::convert(arg);}


The advantage of using the result_type typedef is that you could have converter<T,T> return a const Vec<T>& rather than a Vec<T> if you wanted to, and the client code wouldn't be any wiser.
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
You could overload the function if you took both vectors as arguements, but I think the best solution to this particular problem is an explicit templatized constructor in the vec3 class. The normal conversion then would invoke the regular copy ctor and conversion from another vector would invoke your template ctor.

template<typename T>struct Vec3{   Vec3() {}   Vec3(T x, T y, T z) : x(x), y(y), z(z) {}   Vec3(const Vec3& copy) : x(copy.x), y(copy.y), z(copy.z) {}   template<typename S>   explicit Vec3(const Vec3<S>& copy) : x(copy.x), y(copy.y), z(copy.z) {}};Vec3<int> origin(0,0,0);Vec3<float> origin2(Vec3<float>(origin));
- The trade-off between price and quality does not exist in Japan. Rather, the idea that high quality brings on cost reduction is widely accepted.-- Tajima & Matsubara
Tnx all :)

@Verg:
Yes, but in your sample code you assumed we already know one of the two template type arguments, and this is not my case.

@Shannon Barber
Your solution should be the best one in this simple case, but the example I shown was only for explanatory purpose. (consider, for the sample, if i can't modify the Vec3 definition...)

@Fruny
I heard/maybe knew that partial template specialization is not allowed on non-member functions. However, I think your solution is what I was searching and it seems quite elegant :)

Thanx all you guys!!!

This topic is closed to new replies.

Advertisement