我正在尝试使用一些方法/运算符等来编写模板化的类。现在,当类具有特定类型时,我希望有额外的追加方法,特别适用于那种类型,不适用于任何其他类型。我不想将所有代码复制到一个新类中。
示例:
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)
{
}
}
这是可能的吗?
格尔茨, 理查德。
答案 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)
如果您希望在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)
{
}
答案 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)
// --*-- 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
成员函数,因为编译器不允许它。如果你不使用该方法编译器将优化它,所以它不会存在于代码中。