Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Extra method in template specialization

Tags:

c++

templates

I'm trying to write an templated class with some methods/operators etc.. Now when the class is of an specififc type i would like to have extra append methods specially suited for that type which arent there for any other type. I dont' want to copy all the code into an new class.

Example:

template<typename T>
class Buffer
{
    Buffer(const Buffer<Type> &Buffer) : mData(Buffer.mData)
    {               
    }

    Buffer<Type> Clone()
    {
    }

    void Append (T * aData)
    {
    }

    // this one should only be there when Type is an unsigned char
    void Append (wchar_t * aData)
    {
    }

}

is this at all possible?

Greetz, Richard.

like image 326
Richard Avatar asked Feb 28 '11 14:02

Richard


2 Answers

Directly this is impossible. Full specialization is full specialization which means you must implement the specialized class from scratch. However I can suggest the following trick:

template<class T>
class CommonFunctionality
{
   //your methods here
};

template<class T>
class MyClass: public CommonFunctionality<T>
{
};

template<>
class MyClass<MyType>:public CommonFunctionality<MyType>
{
  public:
    //your extra method here
};

thanks to Mark's suggestion, here's what you can do with the clone method:

template<class T, class ActualType>
class CommonFunctionality
{
   //your methods here
   ActualType Clone(){...}
};

template<class T>
class MyClass: public CommonFunctionality<T, MyClass<T> >
{
};

template<>
class MyClass<MyType>:public CommonFunctionality<MyType, MyClass<MyType> >
{
  public:
    //your extra method here
};
like image 111
Armen Tsirunyan Avatar answered Sep 30 '22 13:09

Armen Tsirunyan


Use a policy class to manage the interaction with the type, then your class doesn't really have to worry about the type that is passed in, an appropriate policy (and specialization of said policy) can contain all the logic specific to that type.

#include <iostream>
#include <vector>

template <typename T, typename U>
struct append_policy
{
  template <typename BufferType>
  static void append(BufferType& buffer, U type)
  {
    std::cout << "default: append U" << std::endl;
  }
};

template <typename U>
struct append_policy<std::string, U>
{
  template <typename BufferType>
  static void append(BufferType& buffer, U type)
  {
    std::cout << "string: append U" << std::endl;
  }
};

template <>
struct append_policy<std::string, char>
{
  template <typename BufferType>
  static void append(BufferType& buffer, char type)
  {
    std::cout << "string: append char" << std::endl;
  }
};

template <typename T>
struct foo
{
  template <typename U>
  void append(U a)
  {
    append_policy<T, U>::append(buffer, a);
  }

  std::vector<char> buffer;
};

int main(void)
{
  foo<std::string> f;
  std::string test("test");
  f.append(test);
  f.append('C');

  foo<int> f1;
  f1.append(0);

  return 0;
}

EDIT: now allows you to append any type to any type of MyClass, and allows you to override specific combination of types, and potentially throw exceptions in other combinations which you don't want to support.

like image 32
Nim Avatar answered Sep 30 '22 14:09

Nim