0

Trying to print a map<string, vector<string>>, but I keep getting the error:

prob2.cc: In function âvoid printMap(const std::map<std::basic_string<char>, std::vector<std::basic_string<char> > >&)â: prob2.cc:42:36: error: cannot bind âstd::basic_ostream<char>::__ostream_type {aka std::basic_ostream<char>}â lvalue to âstd::basic_ostream<char>&&â In file included from /opt/centos/devtoolset-1.1/root/usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../include/c++/4.7.2/iostream:40:0,

I have no idea what it means, cannot bind ostream lvalue to ostream&& in file iostream.

void printMap(const map<string, vector<string>> &mymap)
{
for(auto const& i : mymap)
  cout << i.first << endl << i.second << endl;  //wanting to print out the vector of
}                                              //strings belonging to each string key
CChiste
  • 131
  • 1
  • 2
  • 13
  • use this dude [prettyprint](https://github.com/louisdx/cxx-prettyprint) – aaronman Nov 05 '13 at 04:05
  • 1
    Does it help you at all to know that there is no dump-vector-on-stream operator out of the C++ standard library box? You have to implement it (or just code the functionality inline) yourself. – WhozCraig Nov 05 '13 at 04:08
  • @WhozCraig or use the library I linked, which originated on SO, isn't the goal of all programming to do as little work as possible – aaronman Nov 05 '13 at 04:13
  • @aaronman: The code in that library is illegal. User code is not allowed to add templates inside the `std` namespace, and without adding that template, ADL won't be able to find that `operator<<`. There are alternatives, but you cannot get the operator syntax legally and correctly. – David Rodríguez - dribeas Nov 05 '13 at 04:24
  • @DavidRodríguez-dribeas isn't the code just in the global namespace not the `std` – aaronman Nov 05 '13 at 04:26
  • @aaronman: Line 287 opens the `std` namespace to provide the templated `operator<<` that can be found through ADL. Without defining that template inside the `std` namespace the compiler would fail to find it in many circumstances, but with it the code becomes illegal. Choose your poison. – David Rodríguez - dribeas Nov 05 '13 at 04:28
  • @DavidRodríguez-dribeas yeah just noticed that, but I still choose that poison – aaronman Nov 05 '13 at 04:28
  • @DavidRodríguez-dribeas if you have the heart, you could tell them everything they worked for is for naught [:(](http://stackoverflow.com/questions/4850473/pretty-print-c-stl-containers) – aaronman Nov 05 '13 at 04:32
  • @DavidRodríguez-dribeas sorry to keep commenting on this but I noticed from [this question](http://stackoverflow.com/questions/8513417/what-can-and-cant-i-specialize-in-the-std-namespace) that the behavior is defined if the template is dependent on a UDT, wouldn't it be possible to make it dependent by giving a template param with a default param of a UDT making it dependent. If I'm wrong about this I'll stop commenting :) – aaronman Nov 05 '13 at 23:27
  • @aaronman: No, you are not allowed to add a new base template (this case), only to *specialize* an existing template for a user defined type, but not to add a different base template, which is what is being done in the library. (Note that even if there was a templated `operator<<` in `::std` that is still a base template, you cannot partially specialize a function template) – David Rodríguez - dribeas Nov 06 '13 at 02:36

1 Answers1

1

There is no stream output operator for vector<string> (which is the type of i.second). You need to iterate through the vector. You can define an operator if you do this a lot:

ostream & operator<<( ostream &s, const vector<string>& v )
{
    // TODO: You choose how you want it to look.
    return s;
}
paddy
  • 60,864
  • 6
  • 61
  • 103
  • You cannot provide a *good* operator to do this. You cannot add it to the `std` namespace, and if you add it to a different namespace ADL won't be able to find it and you will have issues when using it outside of the namespace where it is defined. – David Rodríguez - dribeas Nov 05 '13 at 04:18
  • @DavidRodríguez-dribeas maybe an acceptable situation to use `using namespace output;` – aaronman Nov 05 '13 at 04:21
  • @aaronman: In a header, a using directive is **not** acceptable. Ever. :) – David Rodríguez - dribeas Nov 05 '13 at 04:26
  • @DavidRodríguez-dribeas this is not a header – aaronman Nov 05 '13 at 04:34
  • 1
    @aaronman: So if it is not in a header, what will happen in the next translation unit where you need printing of a vector? ODR violation? This is a non-trivial problem to solve, it looks much easier than it really is. If you only need this in a translation unit, a named function is a much better match than attempting to overload an operator, it allows for simpler qualification and avoids the need for the using directive. – David Rodríguez - dribeas Nov 05 '13 at 04:45
  • Thank you for the information on the type of i.second, so I can currently iterate through the map but I can't figure out how to iterate through the vector as it doesn't actually have a name – CChiste Nov 05 '13 at 04:52
  • 2
    Sure it does, `i.second`. `for(size_t z = 0; z < i.second.size(); ++z) {print stuff}` as an example. – Retired Ninja Nov 05 '13 at 04:54
  • AH! Sigh, thank you gentlemen. I was making this far more difficult than it was. Kudos! – CChiste Nov 05 '13 at 05:05