代码之家  ›  专栏  ›  技术社区  ›  user2754048

如何处理模板化类中的ostream运算符重载

  •  0
  • user2754048  · 技术社区  · 11 年前

    所以我有一个名为list的模板类

    //List.h
    #ifndef LIST_H
    #define LIST_H
    #include<fstream>
    
    template <class T>
    class List
    {
        private:
            struct ListNode
            {
               T value;
               ListNode* next;
               ListNode* prev;
    
               ListNode(T value1, ListNode* next1 = NULL, ListNode* prev1 = NULL)
               {
                value = value1;
                next = next1;
                prev = prev1;
               }
            };
            ListNode* head;
            ListNode* tail;
    
       public:
           List() {head = NULL; tail = NULL;};
           ~List();
           void PrintForward(std::ostream &out);
           void PrintBackward(std::ostream &out);
           void InsertFront(const T &item);
           void InsertRear(const T &item);
           bool InsertAsNth(int N, const T &item);
           bool DeleteFront(T &val);
           bool DeleteRear(T &val);
           bool DeleteNth(int N, T &val);
           int DeleteAllOccur(const T &item);
    
           std::ostream& operator<< (std::ostream &out, List::ListNode const* p);
    
    };
    #endif
    

    现在我一直在尝试将其编译,但没有成功。我知道这与我让ostream操作员过载的方式有关,但不幸的是,我真的不知道/找不到更好的方法。

    这也是我的编译器错误

     warning C4346: 'List<T>::ListNode' : dependent name is not a type prefix with 'typename' to indicate a type
    
    3 回复  |  直到 11 年前
        1
  •  3
  •   Janick Bernet    11 年前
    std::ostream& operator<< (std::ostream &out, List::ListNode const* p);
    

    必须成为

    std::ostream& operator<< (std::ostream &out, typename List::ListNode const* p);
    

    甚至可能

    std::ostream& operator<< (std::ostream &out, typename List<T>::ListNode const* p);
    

    更明确一点。

    因为 ::ListNode 是模板化类的依赖类型 List 并且C++编译器需要一点提示。在这种情况下,警告实际上非常有用,对于许多与模板相关的警告来说,这是不可能的:)

        2
  •  1
  •   Community CDub    7 年前

    编译器错误准确地说明了什么是错误的以及您必须做什么: List<T>::Node 是一个依赖于模板参数的限定id,因此编译器无法确定是否 Node 是一种类型或值。所以你必须写 typename 然后告诉编译器 节点 是一种类型。

    我建议你解决这个问题: Where and why do I have to put the "template" and "typename" keywords?

        3
  •  0
  •   James Kanze    11 年前

    您的代码至少有两个主要问题。最多 关键是你正在 operator<< 成员,以及 试图给它三个参数,这是完全非法的。 如果第一个参数是 std::ostream& ,没有 您可以将其定义为成员的方式;它必须是一个自由函数。 如果它还需要访问私人数据,那么您必须 让它成为朋友。但请注意:

    friend std::ostream& operator<<( std::ostream&, typename List::ListNode const* );
    

    交一个非模板函数的朋友。不同的非模板 用于模板的每个实例化的函数。这很少 需要什么。您可以进行特定的模板实例化 友元,但前提是模板函数在 手在这种情况下这是不可能的,因为 函数的参数具有嵌套类型。更地道的 解决这个问题的方法(无论如何,根据我的经验)是定义 好友联机:

    friend std::ostream& operator<<( std::ostream& dest, typename List::ListNode const& p )
    {
        //  ...
    }
    

    在这种情况下, 运算符<&书信电报; 也是一个非模板化函数,但是 该定义嵌套在类模板中,因此您将得到 函数的一个新实例。