模板专业化中的额外方法

时间:2011-02-28 14:34:34

标签: c++ templates

我正在尝试使用一些方法/运算符等来编写模板化的类。现在,当类具有特定类型时,我希望有额外的追加方法,特别适用于那种类型,不适用于任何其他类型。我不想将所有代码复制到一个新类中。

示例:

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 个答案:

答案 0 :(得分:7)

直接这是不可能的。完全专业化是完全专业化,这意味着您必须从头开始实现专业化的类。不过我可以建议以下技巧:

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

感谢Mark的建议,这是你可以用克隆方法做的事情:

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 :(得分:1)

使用策略类来管理与类型的交互,然后您的类实际上不必担心传入的类型,适当的策略(以及所述策略的特化)可以包含特定于的所有逻辑那种类型。

#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,并允许您覆盖特定的类型组合,并可能在您不想支持的其他组合中抛出异常。

答案 2 :(得分:0)

如果您希望在Tunsigned 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)
{
}

答案 3 :(得分:0)

您可以通过Append()中的class Buffer获得一种方法。类似的东西:

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

并且有这样的专业化:

template <>
void Append(Buffer<wchat_t>* pBuffer, wchar_t* pData);

答案 4 :(得分:0)

使用partial specialization

// --*-- 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);
}

答案 5 :(得分:0)

您可以使用

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