Дополнительный метод в специализации шаблона - PullRequest
6 голосов
/ 28 февраля 2011

Я пытаюсь написать шаблонный класс с некоторыми методами / операторами и т. Д. Теперь, когда класс имеет определенный тип, я хотел бы иметь дополнительные методы добавления, специально предназначенные для этого типа, которых нет для любого другого типа.Я не хочу копировать весь код в новый класс.

Пример:

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)
    {
    }

}

это вообще возможно?

Привет, Ричард.

Ответы [ 6 ]

7 голосов
/ 28 февраля 2011

Прямо это невозможно.Полная специализация - полная специализация, что означает, что вы должны реализовать специализированный класс с нуля.Однако я могу предложить следующий трюк:

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
};

, благодаря предложению Марка, вот что вы можете сделать с помощью метода клонирования:

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
};
1 голос
/ 28 февраля 2011

Используйте класс политики для управления взаимодействием с типом, тогда вашему классу на самом деле не нужно беспокоиться о передаваемом типе, соответствующая политика (и специализация указанной политики) может содержать всю логику, специфичную дляэтот тип.

#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;
}

РЕДАКТИРОВАТЬ: теперь позволяет добавлять любой тип к любому типу MyClass и позволяет переопределять определенную комбинацию типов и потенциально генерировать исключения в других комбинациях, которые вы не 'не хочу поддерживать.

0 голосов
/ 28 февраля 2011

Вы можете использовать

template<class T1, class T2>
struct check_equal;

template<class T1>
struct check_equal<T1, T1> {};

template<typename T>
class Buffer
{
    int mData;
public:
    Buffer(): mData(0) {}
    Buffer(const Buffer<T> &buffer) : mData(buffer.mData) {}

    void Append (T * aData)
    {
    }

    void Append (wchar_t * aData)
    {
        check_equal<T, unsigned char>();
        // ...
    }
};

Таким образом, вы не можете использовать Append(wchar_t*) функцию-член, если T не unsigned char, потому что компилятор не допустит этого.И если вы не используете метод, компилятор оптимизирует его, поэтому он не будет существовать в коде.

Чек http://www.ideone.com/mh9Rk

0 голосов
/ 28 февраля 2011

Использование частичная специализация :

// --*-- C++ --*--

#include <cstdio>

template <typename T>
class Buffer
{
public:
    Buffer () {}

    void Append (const T * aData)
    {
        printf ("Data ptr = %p\n", aData);
    }
};

// Special implementation for `wchar_t` case.
template <>
void Buffer<wchar_t>::Append (const wchar_t * aData)
{
    printf ("wchar_t ptr = %p\n", aData);
}

int main ()
{
    Buffer<char> a;
    a.Append (NULL);

    Buffer<wchar_t> b;
    b.Append (NULL);
}
0 голосов
/ 28 февраля 2011

Один из способов добиться этого - набрать Append() из class Buffer.Что-то вроде:

template <typename T>
void Append(Buffer<T>* pBuffer, T* pData);

и специализация такая:

template <>
void Append(Buffer<wchat_t>* pBuffer, wchar_t* pData);
0 голосов
/ 28 февраля 2011

Если вы хотите, чтобы обе функции были доступны, когда T равен unsigned char, то сделайте следующее:

template<typename T>    
struct AddExtraAppend{}; //empty 

template<>              
struct AddExtraAppend<unsigned char> //T=unsigned char,so define a function
{
   void Append (wchar_t * aData)
   {
   }    
};

template<typename T>
class Buffer : AddExtraAppend<T>
{
   void Append (T * aData)
   {
   }    

   //Dont define Append(wchar_t *) here
   //Because if T is unsigned char, it will be inhereted from AddExtraAppend<>
};

Это основная идея.Вы можете комбинировать его с CRTP для достижения своей цели.


Однако, если вам нужна только одна функция, вы можете сделать это.param<> шаблон класса как,

template<typename T> 
struct param { typedef T type; };

template<> //specialization to satisfy your requirement!
struct param<unsigned char> { typedef wchar_t type; };

Затем определите только одну функцию (вместо двух) как:

void Append (typename param<T>::type * aData)
{
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...