This comes from a larger context, however I have stripped alot of code to simplify the question. If you feel I have left anything out please let me know.
Lets say you have a template class defined as:
#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;
};
and inside the friend method “operator<<“
You want to print the conents of the map and the generic container how would one go about doing this? How do you get an appropriate iterator to iterate through the contents of the generic container.
I am trying it with:
container::iterator cbi;
CODE UPDATE
With:
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;
}
I am getting the following compiler error:
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> >)’
What am I missing?
Use
typename:Because
iteratoris a dependent name, as it depends on the type argumentcontainerof the class template. Interestingly, if you’ve corrected usedtypenamein other place, such as inoperator<<:Since you’re working with
const_iteratorfor the map which means the container objects which you would get using map’s const iterator will beconstobjects, which in turn implies you need to useconst_iteratorfor the containers as well, because they are the values of the map. So I think you need to use this:Reply to your edit:
I see a typo here:
The second argument to
std::copyshould beebi, notmbi. That is why I usually name such variables asbeginandend, instead ofcbiandebi.