【问题标题】:C++ operator++ overloading for template iterator of a template generic tree class模板泛型树类的模板迭代器的 C++ operator++ 重载
【发布时间】:2014-08-23 16:40:25
【问题描述】:

我开发了一个 c++ 树模板类,我想为其编写一组自定义迭代器。

GenericTree 类迭代器应按如下方式使用:

GenericTree<int> tree;
GenericTree<int>::iterator<PREORDER> preorder_iterator;

for(preorder_iterator = tree.begin(); preorder_iterator != tree.end(); ++preorder_iterato){
  //Do something on the node pointed by the preorder_iterator.
}

在上面的例子中,++preorder_iterator 应该为 int 和 FORWARD 类型定义的迭代器类调用重载的 operator++() 方法,但是代码不能编译。我正在使用 g++ (Ubuntu 4.8.2-19ubuntu1) 4.8.2

这是迭代器类的代码。为了缩短示例,我将 GenericTree 类替换为向量,并且完全省略了 begin() 方法源代码。

#include <iostream>
#include <string>
#include <vector>

using namespace std;

template<typename P> class GenericTree{
        public:
                vector<P> data;
                GenericTree() {}
                ~GenericTree(){}

        class PREORDER{
        };

        class POSTORDER{
        };

        // ----------------------------------------------------------------------------------
        template<typename IT> class my_iterator : public std::iterator<std::forward_iterator_tag, P> {
                private:
                        int index;
                protected:
                public:
                        my_iterator()           { index=0; }
                        ~my_iterator()  {}

                IT& operator++();
        };
// ----------------------------------------------------------------------------------
        template<> my_iterator<PREORDER>& my_iterator<PREORDER>::operator++(){
                cout << "Preorder visit of GenericTree of nodes containing int values." << endl;
                return (*this);
        }

        template<> my_iterator<POSTORDER>& my_iterator<POSTORDER>::operator++(){
                cout << "Postorder visit of GenericTree of nodes containing int values." << endl;
                return (*this);
        }
};


int main(int argc, char** argv){
        GenericTree<int> c_int;
        GenericTree<int>::my_iterator<GenericTree<int>::PREORDER> iterator_int;

        for(iterator_int = c_int.begin(); iterator_int != c_int.end(); ++iterator_int)
                ;

        GenericTree<string> c_string;
        GenericTree<string>::my_iterator<GenericTree<string>::POSTORDER> iterator_str;

        for(iterator_str = c_string.begin(); iterator_str != c_string.end(); ++iterator__str)
                ;


}

虽然是部分代码,但之前的代码返回的编译错误与我在构建完整源代码时遇到的编译错误相同:

g++     prova.cpp   -o prova
prova.cpp:35:11: error: explicit specialization in non-namespace scope ‘class GenericTree<P>’
  template<> my_iterator<PREORDER>& my_iterator<PREORDER>::operator++(){
           ^
prova.cpp:35:70: error: invalid use of incomplete type ‘class GenericTree<P>::my_iterator<GenericTree<P>::PREORDER>’
  template<> my_iterator<PREORDER>& my_iterator<PREORDER>::operator++(){
                                                                      ^
prova.cpp:24:30: error: declaration of ‘class GenericTree<P>::my_iterator<GenericTree<P>::PREORDER>’
  template<typename IT> class my_iterator : public std::iterator<std::forward_iterator_tag, P> {
                              ^
prova.cpp:40:11: error: explicit specialization in non-namespace scope ‘class GenericTree<P>’
  template<> my_iterator<POSTORDER>& my_iterator<POSTORDER>::operator++(){
           ^
prova.cpp:40:72: error: invalid use of incomplete type ‘class GenericTree<P>::my_iterator<GenericTree<P>::POSTORDER>’
  template<> my_iterator<POSTORDER>& my_iterator<POSTORDER>::operator++(){
                                                                        ^
prova.cpp:24:30: error: declaration of ‘class GenericTree<P>::my_iterator<GenericTree<P>::POSTORDER>’
  template<typename IT> class my_iterator : public std::iterator<std::forward_iterator_tag, P> {
                              ^
prova.cpp: In function ‘int main(int, char**)’:
prova.cpp:51:27: error: ‘class GenericTree<int>’ has no member named ‘begin’
  for(iterator_int = c_int.begin(); iterator_int != c_int.end(); ++iterator_int)
                           ^
prova.cpp:51:58: error: ‘class GenericTree<int>’ has no member named ‘end’
  for(iterator_int = c_int.begin(); iterator_int != c_int.end(); ++iterator_int)
                                                          ^
prova.cpp:57:30: error: ‘class GenericTree<std::basic_string<char> >’ has no member named ‘begin’
  for(iterator_str = c_string.begin(); iterator_str != c_string.end(); ++iterator__str)
                              ^
prova.cpp:57:64: error: ‘class GenericTree<std::basic_string<char> >’ has no member named ‘end’
  for(iterator_str = c_string.begin(); iterator_str != c_string.end(); ++iterator__str)
                                                                ^
prova.cpp:57:73: error: ‘iterator__str’ was not declared in this scope
  for(iterator_str = c_string.begin(); iterator_str != c_string.end(); ++iterator__str)
                                                                         ^
make: *** [prova] Error 1

我找不到为 PREORDER 和 POSTORDER 类型定义 operator++() 的两个模板特化的正确方法。

如果我使用 template&lt;&gt; 关键字,编译器会抱怨特化超出范围,我不明白为什么。 将两个模板特化移出 GenericTree 类主体并没有解决问题。

提前感谢您的帮助!

f.

【问题讨论】:

标签: c++ templates tree iterator


【解决方案1】:

将迭代器类移出GenericTree 和部分专业化 struct my_iterator 完成这项工作。 以下编译并可能有所帮助:

namespace internal
{
    class PREORDER {};
    class POSTORDER {};

    // ------------------------------------------------------------------------------
    template<typename P, typename IT>
    class my_iterator;


    template<typename P>
    class my_iterator<P, PREORDER>
    : public std::iterator<std::forward_iterator_tag, P>
    {
    private:
        int index;
    protected:
    public:
        my_iterator () { index = 0; }

        my_iterator& operator++ () {
            std::cout << "Preorder visit of GenericTree of nodes containing int values." << std::endl;
            return (*this);
        }
    };
    // ------------------------------------------------------------------------------
    template<typename P>
    class my_iterator<P, POSTORDER>
    : public std::iterator<std::forward_iterator_tag, P>
    {
    private:
        int index;
    protected:
    public:
        my_iterator () { index = 0; }

        my_iterator& operator++ () {
            std::cout << "Postorder visit of GenericTree of nodes containing int values." << std::endl;
            return (*this);
        }
    };

}

template<typename P> class GenericTree
{
public:
    template <typename IT>
    using my_iterator = internal::my_iterator<P, IT>;
    using PREORDER = internal::PREORDER;
    using POSTORDER = internal::POSTORDER;

    std::vector<P> data;
    GenericTree () {}
    ~GenericTree () {}
};

Demo

【讨论】:

  • 但是如果我在实例化迭代器以在树上工作时将迭代器类移出 GenericTree 类,我应该将树指针/引用传递给迭代器以便能够遍历树结构。如果我设法将 iteraror 类保留在 GenericTree 中,那么在我看来,要编写使用两者的代码就很清楚了。
  • 如果两个类保持嵌套,你认为问题可以解决吗?
  • 不确定我是否理解您的第二条评论,但我在GenericTree 中提供了typedef 以允许使用相同的界面。确实,在类GenericTree的定义之后,你可能要实现my_iterator的一些方法。
  • 我在这里可能错了,但要使用你的 my_iterator 实现,我应该写类似: GenericTree tree_int; my_iterator iter_int(&tree)。也就是说,我应该以某种方式向 iter_int 传递一个指向它应该迭代的树的指针。
  • 如果您添加一个虚拟类型以保持内部类部分专业化,似乎可以保持类嵌套。
猜你喜欢
  • 2012-07-01
  • 1970-01-01
  • 2017-11-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-18
相关资源
最近更新 更多