C ++ - 确定泛型变量是否为指针

时间:2013-12-30 03:34:48

标签: c++ templates pointers containers

我有一个类,我将其称为myclass,它有一个类型为T的列表容器。我还有一些方法可以从列表中删除项目。如果T是某种指针,我想检查它确实是一个指针,然后将其删除,以便将分配的资源释放回内存。这是一段代码:

template<typename T>
class myclass{
private:
    std::list<T> * container;
    // other vars
public:

    void erase(const T &item){
        if (!this->find(item))     // find is defined elsewhere
            return false;
        auto temp = container->begin();
        for (int i = 0; i < container->size(); ++i){
            // this is where i would like to check if *temp is a pointer,
            // so that I can assign it to a pointer var, remove it from the list,
            // then delete the pointer,
            //otherwise just simply remove it from the list.
        }
    }

};

修改

auto temp = container->begin();

我想知道如何确定* temp是否为指针,以便我可以执行以下操作:

T * var = *temp;
container->remove(temp);   // remove or erase, i can't recall at the moment
delete var;

但如果* temp是指针

,我只想这样做

4 个答案:

答案 0 :(得分:3)

1)Determine if Type is a pointer in a template function

2)你怎么知道那个指针是否指向动态分配的内存?

答案 1 :(得分:2)

很抱歉,但是没有:std::list<T>::iterator(这将是begin()将返回的,因此将是temp的类型)不能成为指针。 必须是一种类型(至少)重载前后增加和减少以进行链表遍历,因此++将执行pos = pos->next;和{--之类的操作{1}}类似于pos = pos->prev;

如果你想弄清楚*temp(与T的类型相同)是否是一个指针,那就完全不同了。你基本上有两条路线。作为一般规则,我更喜欢的是为指针提供类的特化:

template<typename T>
class myclass{
private:
    std::list<T> container;
    // other vars
public:

    void erase(const T &item){
        if (!container->find(item))     // find is defined elsewhere
            return false;
        auto temp = container->begin();
        for (int i = 0; i < container->size(); ++i){
            container.erase(temp);
        }
    }

};

template<class T>
class myclass <T *> {
private:
    std::list<T> container;
    // other vars
public:

    void erase(const T &item){
        if (!container->find(item))     // find is defined elsewhere
            return false;
        auto temp = container->begin();
        for (int i = 0; i < container->size(); ++i){
            delete *temp;
            container.erase(temp);
        }
    }
};

这个问题的最大问题是你最终可能会在基本模板和指针专门化之间复制相当数量。有几种方法可以避免这种情况。一种是使用实现公共行为的基类,然后从中派生两个特化以提供特殊行为。另一种方法是使用一些enable_if或SFINAE来启用erase函数的不同版本,具体取决于所包含的类型是否可以被解除引用。

顺便说一下,你可能不应该std::list<T> *container; - 它应该只是std::list<T> container;(或者,在大多数情况下更好,{{1} })

答案 2 :(得分:1)

我不认为这是一个明智的想法。您不知道用户是否提供了指向堆栈上分配的数据的指针,或者是否以其他方式管理的数据(例如,使用智能指针)。

但要回答这个问题,请看

std::is_pointer<T>::value  // in type_traits header

http://en.cppreference.com/w/cpp/types/is_pointer

这是C ++ 11的一项功能。

答案 3 :(得分:0)

不是烦人的容器不删除普通指针吗?在C ++中,原始指针实际上并不拥有该对象。可能有许多指针指向同一个对象。你需要一个唯一的指针 - stl在c ++ 11中提供一个。当从列表中删除unique_ptr时,它将销毁它指向的对象,因此不需要复杂擦除。

#include <list>
#include <memory>
#include <type_traits>

using namespace std;

template<typename t, bool b>
struct Selector {
    typedef list<T> container;
};

template<typename t>
struct Selector<t, true> {
    typedef list<unique_ptr<T> > container;
};

template<typename T>
class myclass{
private:
    Selector<T, is_pointer<T>::value>::container* container;
    // other vars
public:

    void erase(const T &item){
        if (!this->find(item))     // find is defined elsewhere
            return false;
        auto temp = container->begin();
        for (int i = 0; i < container->size(); ++i){
            // removing the unique_ptr delete's pointer
        }
    }
};