Search code examples
c++templatesspecializationpartial-specialization

Template partial specialization problems


I am trying to write a size and type generic vector class for math programming. I am having problems with partial specialization.

The problem occurs when I try to specialize a member method of my vector class for given size.

I can provide a simple example:

template <size_t Size, typename Type>
class TestVector
{
public:
    inline TestVector (){}
    TestVector cross (TestVector const& other) const;
};

template < typename Type >
inline TestVector< 3, Type > TestVector< 3, Type >::cross (TestVector< 3, Type > const& other) const
{
    return TestVector< 3, Type >();
}

void test ()
{
    TestVector< 3, double > vec0;
    TestVector< 3, double > vec1;
    vec0.cross(vec1);
}

When trying to compile this simple example I get a compilation error stating the 'cross' specialization does not match an existing declaration:

error C2244: 'TestVector<Size,Type>::cross' : unable to match function definition to an existing declaration
see declaration of 'TestVector<Size,Type>::cross'
definition
    'TestVector<3,Type> TestVector<3,Type>::cross(const TestVector<3,Type> &) const'
    existing declarations
    'TestVector<Size,Type> TestVector<Size,Type>::cross(const TestVector<Size,Type> &) const'

I have tried to declare cross as a template:

template <size_t Size, typename Type>
class TestVector
{
public:
    inline TestVector (){}

    template < class OtherVec >
    TestVector cross (OtherVec const& other) const;
};

template < typename Type >
TestVector< 3, Type > TestVector< 3, Type >::cross< TestVector< 3, Type > > (TestVector< 3, Type > const& other) const
{
    return TestVector< 3, Type >();
}

This version passes compilation but fails at link-time:

 unresolved external symbol "public: class TestVector<3,double> __thiscall TestVector<3,double>::cross<class TestVector<3,double> >(class TestVector<3,double> const &)const

What am I missing here ? Thanks, Florent


Solution

  • One way to do this is to define cross as a "functor" (that is, a class with an operator()).

    template<size_t S, typename T>
    class Vec {
      // ... stuff
      friend struct Cross<S, T>;
      Vec<S, T> cross(const Vec<S, T>& other) {
        return Cross<S, T>()(*this, other);
      }
      // ... more stuff
    };
    
    
    template<size_t S, typename T> struct Cross {
      Vec<S, T> operator() (const Vec<S, T>& a, const Vec<S, T>& b) {
        // general definition
      }
    };
    
    // Partial specialization
    template<typename T> struct Cross<3, T> {
      vec<3, T> operator() (const Vec<3, T>& a, const Vec<3, T>& b) {
        // specialize definition
      }
    };