【问题标题】:getting an iterator to a generic container inside a generic class: HOW TO在泛型类中获取泛型容器的迭代器:如何
【发布时间】:2011-12-15 18:26:34
【问题描述】:

这来自一个更大的背景,但是我已经剥离了很多代码来简化问题。如果您觉得我遗漏了什么,请告诉我。

假设您有一个模板类定义为:

#include <map>
#include <vector>
#include <string>
#include <fstream>
#include <iostream>
#include <iterator>
#include <algorithm>
template <class key, class container, class container_type>
class file_to_map
{
public:
  file_to_map()
  {
    m_file = "";
  }

  file_to_map(std::string file)
  {
    m_file = file;
  }

  ~file_to_map()
  {
  }

  std::map<key, container>& get_map()
  {
    return m_map;
  }

  void set_file(const std::string file)
  { 
    m_file = file;
  }

  void insert_into_map(key insert, container_type value)
  {
    m_map[insert].insert(value);
  }

  friend std::ostream& operator<< (std::ostream &out, file_to_map<key, container, container_type> &obj)
  {
    typedef typename std::map<key, container>::const_iterator mapItr;
    mapItr mbi = obj.m_map.begin();
    mapItr emi = obj.m_map.end();
    while (mbi != emi) {
      out << " -- " << mbi->first << " -- " << std::endl;
      container::iterator cbi;
      ++mbi;
    }
    return out;
  }

  friend std::istream& operator>> (std::ifstream &in, file_to_map<key, container, container_type> &obj)
  {
    if (in.is_open())
      in.close();

    if (obj.m_file == "")
      return in;

    in.open(obj.m_file.c_str(), std::ios::in);

    if (in.fail() || in.bad()) {
      in.close();
      return in;
    }

    std::vector<key> tmp;
    typedef std::istream_iterator<key> string_input;
    copy(string_input(in), string_input(), back_inserter(tmp));
    typename std::vector<key>::iterator bvi = tmp.begin();
    typename std::vector<key>::iterator evi = tmp.end();
    while (bvi != evi) {
      obj.m_map[*(bvi)] = container();
      ++bvi;
    }

    in.close();
    return in;
  }  
  private:
    std::map<key, container> m_map;
    std::string m_file;
};

在朋友方法里面“operator&lt;&lt;

你想打印地图的内容和通用的container 怎么做呢?如何获得合适的迭代器来遍历泛型 container 的内容。

我正在尝试:

container::iterator cbi;

代码更新

与:

friend std::ostream& operator<< (std::ostream &out, file_to_map<key, container, container_type> &obj)
  {
    typedef typename std::map<key, container>::const_iterator mapItr;
    mapItr mbi = obj.m_map.begin();
    mapItr emi = obj.m_map.end();
    while (mbi != emi) {
      out << " -- " << mbi->first << " -- " << std::endl;
      typename container::const_iterator cbi = mbi->second.begin();
      typename container::const_iterator ebi = mbi->second.end();
      std::copy(cbi, mbi, std::ostream_iterator<container_type>(out, "\t\n"));
      ++mbi;
    }
    return out;
  }

我收到以下编译器错误:

g++ -o file_to_map -Wall ./file_to_map.h ./main.cpp ./code_finder.cpp \
        -L/usr/local/boost_1_48_0/stage/lib -lboost_filesystem -lboost_system -I /usr/local/boost_1_48_0/
In file included from ./code_finder.h:4,
                 from ./code_finder.cpp:1:
./file_to_map.h: In function ‘std::ostream& operator<<(std::ostream&, file_to_map<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::set<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >&)’:
./code_finder.cpp:36:   instantiated from here
./file_to_map.h:62: error: no matching function for call to ‘copy(std::_Rb_tree_const_iterator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >&, operator<<(std::ostream&, file_to_map<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::set<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >&)::mapItr&, std::ostream_iterator<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, char, std::char_traits<char> >)’

我错过了什么?

【问题讨论】:

    标签: c++ templates stl containers


    【解决方案1】:

    使用typename:

    typename container::iterator cbi;
    

    因为iterator 是一个依赖名称,因为它依赖于类模板的类型参数container。有趣的是,如果你已经更正了在其他地方使用过的typename,比如operator&lt;&lt;

    typedef typename std::map<key, container>::const_iterator mapItr;
    

    由于您正在为地图使用const_iterator,这意味着您将使用地图的 const 迭代器获得的 container 对象将是 const 对象,这反过来意味着您需要使用const_iterator 也适用于容器,因为它们是地图的值。所以我认为你需要使用这个:

    typename container::const_iterator cbi; //use this instead!
    

    回复您的编辑:

    我在这里看到一个错字:

    typename container::const_iterator cbi = mbi->second.begin();
    typename container::const_iterator ebi = mbi->second.end();
    std::copy(cbi, mbi, std::ostream_iterator<container_type>(out, "\t\n"));
                // ^^^ typo
    

    std::copy 的第二个参数应该是 ebi,而不是 mbi。这就是为什么我通常将这些变量命名为beginend,而不是cbiebi

    【讨论】:

    • 那条评论帮了大忙,但是我仍然有一些小问题。我已经添加到上面的帖子中,你介意帮我完成这个吗?
    • @MatthewHoggan:也回复了您的编辑。您的代码中有错字。
    • 这就是我在每日构建之前匆忙修复的结果 =(。感谢他的帮助。
    猜你喜欢
    • 1970-01-01
    • 2010-09-05
    • 2015-07-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-20
    • 2013-09-11
    • 1970-01-01
    相关资源
    最近更新 更多