C++ - Separate declaration/definition for template function in template class

Brandon Miller picture Brandon Miller · Nov 12, 2012 · Viewed 24.9k times · Source

I am aware that the syntax for declaring a template class method in a header and defining it in a source file goes as so:

myclass.h

template <typename T>
class MyClass {
  public:
    void method(T input);
  private:
    T privVar;
};

myclass.cpp

template <typename T>
void MyClass<T>::method(T input) {
    privVar = input;
}

But, what if the method is also a template? I am adding methods to the basic_string class, and I want to know how to write the implementation for the functions.

MyString.h

template <class _Elem   = TCHAR,
          class _Traits = std::char_traits<_Elem>,
          class _Ax     = std::allocator<_Elem>>
class String
    : public std::basic_string<_Elem, _Traits, _Ax> {
  private:
    // Types for the conversion operators.
    typedef       _Elem* _StrTy;
    typedef const _Elem* _ConstStrTy;

    //...

  public:
        // Conversion operators so 'String' can easily be
        // assigned to a C-String without calling 'c_str()'.
    operator _StrTy() const {
        return const_cast<_StrTy>(this->c_str());
    }

    operator _ConstStrTy() const {
        return this->c_str();
    }

    // ... Constructors ...

    /*------------ Additional Methods ------------*/

    //! Converts a value of the given type to a string.
    template <class _ValTy> static String ConvertFrom(_ValTy val);

    //! Converts a string to the given type.
    template <class _ValTy> static _ValTy ConvertTo(const String& str);
    template <class _ValTy> _ValTy ConvertTo(void) const;

    //! Checks if a string is empty or is whitespace.
    static bool IsNullOrSpace(const String& str);
    bool IsNullOrSpace(void) const;

    //! Converts a string to all upper-case.
    static String ToUpper(String str);
    void ToUpper(void);

    // ...
};

How could I implement template <class _ValTy> static String ConvertFrom(_ValTy val);? Because now not only do I need to specify the class template, but the function template too. I am betting the code I'm about to write isn't valid, but it should show what I am trying to accomplish:

MyString.cpp

template <class _Elem, class _Traits, class _Ax>
template <class _ValTy>
String<_Elem, _Traits, _Ax> String<_Elem, _Traits, _Ax>::ConvertFrom(_ValTy val) {
    // Convert value to String and return it...
}

I am not advanced at all with templates. Not only am I very doubtful that the above is valid, it seems cumbersome to write and not very readable. How would I go about implementing the template methods, and the static template methods which returns its own class type? Because I don't want to define them in the header.

Answer

Rost picture Rost · Nov 12, 2012

Syntax of definition of template member functions outside of template is like this:

template <class T> struct A
{
   template <class X> void f();
};

template<class T> template<class X> void A<T>::f()
{
}

So your code is correct.

Would like to note that defining template members in .cpp is not very useful. In this case you shall explicitly instantiate them with all types you need to use with this template. Or do not use them outside this .cpp which doesn't make sense.