c ++带模板的析构函数:T可以是指针还是不指针

时间:2014-04-03 20:01:27

标签: c++ templates pointers

我在编写模板类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类比我在这里展示的要大得多)?

谢谢!

3 个答案:

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