Search code examples
c++classooptemplatesmodel

Partially specialized member function on template classes


I have some template classes and I need to implement a specialized member function for the main class. For example, if we have a template class Parent and other two template classes Boy and Girl. I want to implement a member function with specialization for Boy and for Girl. The member function for Girl has one more argument.

Boy and Girl are template class themselves also, so how do I define TT in this code?

template< typename TT >
class Child
{
    TT age;
};

template< typename TT >
class Boy< TT > : public Child< TT > 
{ ... };

class Girl< TT > : public Child< TT >
{ ... };

template<typename T>
class Parent {
private:
    std::vector< T > children;
//public:
//  void ProcessChild() {
//  }
};

template<> void Parent < Boy< TT > >::ProcessChild( TT age ) { // ??
  // implementation for boys
}

template<> void Parent< Girl< TT > >::ProcessChild( TT age, std::string name ) { // ??
  // implementation for girls
}

In this context, T would be a Boy or a Girl and TT would be int or double.

I want two member function specializations for ProcessChild, one for Boy and one for Girl. I can't seem to find the proper syntax for my code, also I can't find any other example where inner class is also a template class. Other examples are specializations of primitive types such as int or double.

I am also trying something like this:

template<>
template< class U >
class Parent < Girl< U > >
{
public:
    template< class TT >
    void ProcessChild( TT age, std::string name )
    {
         //...
    }
};

All the code shown here is not compiling. This is one of the errors I am getting: error: invalid use of incomplete type 'class Parent<Girl<U> >

Extra: my question is an extension from this previous post. I modified the example quite a bit though.


Solution

  • If you wanted to fully specialize the function then you could explicitly instantiate the function to create a specialization, but that won't work in this case since you can't partially specialize function templates.

    In this case, your best bet is probably to pull the non-specialized functionality out into a base class. Then you can partially specialize Parent<Boy<TT>> and Parent<Girl<TT>> and have them both derive from the base class:

    template <typename T>
    class ParentBase {
    protected:
        std::vector<T> children;
    };
    
    template <typename T>
    class Parent;
    
    template <typename TT>
    class Parent<Boy<TT>> : ParentBase<Boy<TT>> {
    public:
        void processChild(TT age) {
          // ...
        }
    };
    
    template <typename TT>
    class Parent<Girl<TT>> : ParentBase<Girl<TT>> {
    public:
        void processChild(TT age, std::string name) {
          // ...
        }
    };
    

    Demo