Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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.

like image 711
Brandon Miller Avatar asked Nov 12 '12 21:11

Brandon Miller


People also ask

How do you declare a template function?

To instantiate a template function explicitly, follow the template keyword by a declaration (not definition) for the function, with the function identifier followed by the template arguments. template float twice<float>( float original ); Template arguments may be omitted when the compiler can infer them.

What is template What is the need of template declare a template class?

Templates in c++ is defined as a blueprint or formula for creating a generic class or a function. To simply put, you can create a single function or single class to work with different data types using templates.

What happens when a function is defined as a template?

Function templates are special functions that can operate with generic types. This allows us to create a function template whose functionality can be adapted to more than one type or class without repeating the entire code for each type. In C++ this can be achieved using template parameters.

What is the difference between class template and template class?

A class template is a template that is used to generate classes whereas a template class is a class that is produced by a template.


1 Answers

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.

like image 158
Rost Avatar answered Sep 30 '22 15:09

Rost