我正在写一个数组类。此数组类可以再次包含数组作为成员。实现打印功能时,我需要专业化。
26:template <class T> class array : public vector<T>{
public:
...
string* printToString();
...
};
...
template <class T> string* array<T>::printToString(){
... // generic function
}
template <> inline string* array<double>::printToString(){
... // spezialization for double, works
}
561:template <class U> string* array<array<U>*>::printToString(){
... // does not work
}
最后一个定义产生
src/core/array.h:561: error: invalid use of incomplete type ‘class array<array<T> >’
src/core/array.h:26: error: declaration of ‘class array<array<T> >’
如果重要的话,g ++版本是g ++(Ubuntu 4.4.3-4ubuntu5)4.4.3。 有什么想法是什么问题?
提前致谢, 托马斯
答案 0 :(得分:4)
作为David解决方案的替代方案,您可以无条件地将调用转发给一组重载函数:
template <class T> class array;
namespace details {
template <class T> std::string array_print(array<T> const&);
std::string array_print(array<double> const&); // Regular function
template <class T> std::string array_print(array<array<T> > const&);
}
template <class T> class array : private vector<T> {
public:
...
std::string printToString() { return details::array_print(*this); }
...
};
namespace details { /* implementions after class is defined */ }
答案 1 :(得分:3)
你不能部分专门化一个功能,你只能完全专门化它,这就是你可以为double
而不是array<U>
U
提供专业化的原因。 {1}}是通用类型。
你可以通过使用类模板解决这个限制,并对其进行部分特殊处理,但这会有点麻烦。
namespace detail {
template <typename T>
struct array_printer {
static std::string print( array<T> const & array ) {
// basic implementation
}
};
template <typename T>
struct array_printer< array<T> > {
static std::string print( array< array<T> > const & array ) {
// specialization for array<T>
}
}
}
然后将成员函数实现为适当重载的简单调度:
template <typename T>
class array : std::vector<T> { // do not publicly derive from STL containers
public:
std::string printToString() const {
return detail::array_printer<T>::print( *this );
}
}
当然,实际代码中的事情要复杂得多,你必须适当地订购代码,并提供模板的前向声明以及所有这些,但这应该足以让你开始。
答案 2 :(得分:1)
您的功能必须完全专业化。例如:
// Fully specialized. You cannot replace `double` with generic parameter.
template <>
string* array<array<double>*>::printToString(){
return nullptr;
}
但是,您的课程可以部分专业化。例如:
template <class T> class array : public vector<T>{
public:
string* printToString();
};
template <class T> string* array<T>::printToString(){
return nullptr;
};
// Partial specialization.
template <class T> class array<array<T>*> : public vector<T>{
public:
string* printToString();
};
template <class T> string* array<array<T>*>::printToString(){
return nullptr;
};
- 编辑---
类通用类中的方法不会被类专门化“自动”采用,反之亦然。但是,您可以使用继承来“自动化”从泛型类重用方法。例如......
template <class T> class array : public vector<T>{
public:
string* printToString();
void f();
};
// (1a)
template <class T> string* array<T>::printToString(){
return nullptr;
};
// (2)
template <class T> void array<T>::f(){
};
template <class T> class array<array<T>*> : public array<T> {
public:
string* printToString();
};
// (1b)
template <class T> string* array<array<T>*>::printToString(){
return nullptr;
};
void Test() {
array<double> a1;
a1.printToString(); // Calls (1a).
a1.f(); // Calls (2).
array<array<char>*> a2;
a2.printToString(); // Calls (1b).
a2.f(); // Calls (2).
}
......这可能是你需要的,也可能不是(可能需要一些“手动”重复)。