我在编写模板类win C ++时遇到了一个小问题。
问题很简单:我不知道是否在paremetrized类型上做delete
,因为它可能,或者它不能成为指针。
我见过这个:Destructor in template class c : How to delete field which may be pointer or not pointer?
并且我已经实现了第一个解决方案,但是这需要我专门化整个类,所以这意味着我必须有两个类:
template<class T>
class Node {
private:
T _content;
public:
Node(const T c);
~Node();
};
和
template<class T>
class Node<T*> {
private:
T _content;
public:
Node(const T c);
~Node();
};
我想只有第二个版本,并且只对 析构函数进行专门化,如下所示:
template<class T>
class Node<T*> {
private:
T _content;
public:
Node(const T c);
~Node();
};
template <class T>
Node<T>::~Node() {
while(!_adjacent.isEmpty()) {
disconnectFrom(_adjacent.first());
}
}
template <class T>
Node<T*>::~Node() {
while(!_adjacent.isEmpty()) {
disconnectFrom(_adjacent.first());
}
delete _content;
}
然后我收到以下错误:
Node.hpp:43:17: error: invalid use of incomplete type ‘class Node<T*>’
Node.hpp:8:7: error: declaration of ‘class Node<T*>’
有没有办法专门化构造函数以避免有2个类(我的Node类比我在这里展示的要大得多)?
谢谢!
答案 0 :(得分:5)
解决方案是使用traits类:
template<typename T> struct delete_traits
{
void destroy(T&) {}
};
template<typename T> struct delete_traits<T*>
{
void destroy(T* p) { delete p; }
};
然后在你的类析构函数中写
delete_traits<T>::destroy(_contents);
除了不必专门化Node
模板之外,它还有一个额外的好处,即您可以轻松地添加其他方法来破坏事物,而无需触及您定义的文件Node
,只需添加另一个模板专业化:
// assumes that mylib_handle is a truly different type, maybe a C struct
// from the C interface of a library
template<> struct delete_traits<mylib_handle>
{
void destroy(mylib_handle& h) { mylib_handle_free(m); }
};
答案 1 :(得分:4)
根本不要专门化Node。只需为你的意图使用正确的类型:
std::unique_pointer<T>
。std::shared_pointer<T>
。
std::weak_pointer<T>
。如果您需要特定的析构函数,那么这些模板都有一个参数 此外,您可以将它们用于句柄等,即使它们不是命名指针。
答案 2 :(得分:3)
似乎你想要这个:
template<class T>
class Node {
private:
T _content;
public:
Node(const T c) : _content { c } {}
~Node() {}
};
template<class T>
class Node<T*> {
private:
T* _content;
public:
Node(const T* c) : _content { c } {}
~Node() { delete _content; }
};
而且,正如@Constructor所说,不,你不能只是专门化析构函数,你必须做全班......但如果这个类更大,你可以重构基类的共性而你' d有类似的东西:
template<class T>
class BaseNode {
private:
template<class> friend class Node;
T _content;
public:
BaseNode(T c) : _content { c } {}
~BaseNode() {}
};
template<class T>
struct Node : BaseNode<T> {
Node(T c) : BaseNode<T>(c) {};
~Node() {}
};
template<class T>
struct Node<T*> : BaseNode<T*> {
Node(T* c) : BaseNode<T*>(c) {};
~Node() { delete BaseNode<T*>::_content; }
};