Reputation: 7604
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?
Upvotes: 0
Views: 1091
Reputation: 361782
Use typename
:
typename container::iterator cbi;
Because iterator
is a dependent name, as it depends on the type argument container
of the class template. Interestingly, if you've corrected used typename
in other place, such as in operator<<
:
typedef typename std::map<key, container>::const_iterator mapItr;
Since you're working with const_iterator
for the map which means the container objects which you would get using map's const iterator will be const
objects, which in turn implies you need to use const_iterator
for the containers as well, because they are the values of the map. So I think you need to use this:
typename container::const_iterator cbi; //use this instead!
Reply to your edit:
I see a typo here:
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
The second argument to std::copy
should be ebi
, not mbi
. That is why I usually name such variables as begin
and end
, instead of cbi
and ebi
.
Upvotes: 7