在模板类上重载<<运算符

Tec*_*Wiz 4 c++ templates operator-overloading

我为链表中的节点创建了一个模板类,我试图让它通过重载<<将其内容输出到输出流.但是我目前的代码:

#include <iostream>
using namespace std;
template<class NType> class Node;

template<class NType>
class Node {
private:
        void deletePointer(NType* p);
public:
        NType data;
        Node *prev, *next;

        template<typename T>
        struct is_pointer { static const bool value = false; };

        template<typename T>
        struct is_pointer<T*> { static const bool value = true; };

        Node();
        Node(NType data);
        ~Node();
};  

int main() {
        Node<int> *n1 = new Node<int>();
        Node<int> *n2 = new Node<int>(10);

        std::cout << "Node 1: " << n1 << std::endl;
        std::cout << "Node 2: " << n2 << std::endl;
}

template<class NType> inline std::ostream & operator << (std::ostream& out, const Node<NType> &node){
        out << node.data;
        return out;
}

template<class NType> inline Node<NType>::Node()
            :data(NULL), prev(NULL), next(NULL)
{
}

template<class NType> inline Node<NType>::Node(NType data)
            :data(data), prev(NULL), next(NULL)
{
}

template<class NType> inline Node<NType>::~Node(){
        if(is_pointer<NType>::value){
                deletePointer(&data);
        } else {
                return;
        }
}

template<class NType> inline void Node<NType>::deletePointer(NType* p){
    delete p;
}
Run Code Online (Sandbox Code Playgroud)

输出内存位置而不是节点内的数据.这种情况发生int在诸如此类的原始类型之类,就像它不知道NType容器中的数据类型一样.

Node 1: 0x741010
Node 2: 0x741030
Node 3: 0x741070
Node 4: 0x741090
Run Code Online (Sandbox Code Playgroud)

我尝试使用typename而不是class但仍然没有骰子...有没有办法动态找出模板在插入之前使用和投射的类型?我知道我可以为所有基元制作大量冗余代码,但这似乎是浪费和不必要的.

如果它有帮助,我正在使用GCC v4.6.2 20111223在Arch Linux x64上进行编译

编辑:因为很多人都提到它.我也尝试将这个类作为朋友和独立函数放在外面,因为无论我把它放在哪里,因为流输出地址而不是数据本身.没有要访问的私有数据值,因此可以不成为朋友.

编辑: 测试用例:http://ideone.com/a99u5 还更新了上面的源代码.

编辑: 添加了我的代码的剩余部分,以帮助Aaron理解代码.

Gri*_*zly 8

您的代码声明operator<<为成员函数,因此它实际上将this指针作为第一个参数和ostream第二个参数.相反,它需要是一个自由功能:

template<class NType> class Node {
public:
    NType data;
    Node *prev, *next;
};
//Note how this is declared outside of the class body, so it is a free function instead of a memberfunction
template<class NType> inline std::ostream& operator<<(std::ostream& out, const Node<NType>& val){
    out << val.data;
    return out;
}
Run Code Online (Sandbox Code Playgroud)

但是,如果您operator<<需要访问私有数据,则需要将其声明为友元函数:

template<class NType> class Node {
public:
    NType data;
    Node *prev, *next;
    friend std::ostream& operator<<(std::ostream& out, const Node& val){
        out << val.data;
        return out;
    }
};
Run Code Online (Sandbox Code Playgroud)

现在输出:如果你operator<<被调用,编译器会知道NType流式传输data成员时的类型并做正确的事情.但是,既然你operator<<不应该工作(如写)并且它似乎给你memoryaddresses作为输出我会假设你有类似以下的东西:

Node* n = new Node();
std::cout<<n;
//When it should be:
std::cout<<*n;
Run Code Online (Sandbox Code Playgroud)

现在只是出于好奇的缘故:你为什么要自己实现看起来像链接列表而不仅仅是使用std::list

编辑: 现在我们可以看到测试用例似乎是关于operator<<被调用的假设是正确的.输出需要更改为:

std::cout << "Node 1: " << *n1 << std::endl;
std::cout << "Node 2: " << *n2 << std::endl;
Run Code Online (Sandbox Code Playgroud)

实际调用operator<<for Node,而不是泛型forT*

  • @TechWiz:亲爱的,不要抱着这种感觉,它会很快再次回到你身边.;) (2认同)