2

I am attempting to print containers, like sets and maps. The book I am using says the following code is valid:

#include <iostream>
#include <set>
#include <iterator>
#include <fstream>
using namespace std;

template <typename Container>
void print (const Container & c, ostream & out = cout)
{
    typename Container::const_iterator itr;
    for( itr=c.begin(); itr!=c.end(); ++itr)
        out << *itr << " ";
    out << endl;
}

int main()
{
    ifstream fin("Test.txt");
    set<string> s(  istream_iterator<string>(fin),
                    istream_iterator<string>() );
    print( s );

    return 0;
}

Yet I am getting the an error from Visual Studio's compiler. What am I missing? I know it is likely something simple like an include yet I am unfamiliar with STL Containers and C++ iterators.

I already have #include <iterator>

Errors:

  • 'Container': must be a class or namespace when followed by '::'
  • 'itr' : undeclared identifier
  • 'const_iterator' : is not a member of '`global namespace''

and a few more I am sure are a result of the first one.

Edit:

Per the textbook, the following code should be equivalent to that in my main. I could not get it to work but it may help:

ifstream fin("Test.txt");
string x;
set<string> s;
while( fin >> x)
    s.insert(x);

Edit:

Visual Studio build output:

------ Build started: Project: project, Configuration: Debug Win32 ------
Build started 4/15/2012 1:19:25 PM.
InitializeBuildStatus:

  Touching "Debug\project.unsuccessfulbuild".

ClCompile:

  Project4.cpp

c:\users\admin\documents\visual studio 2010\projects\project\project\project4.cpp(11): error C2825: 'Container': must be a class or namespace when followed by '::'

          c:\users\admin\documents\visual studio 2010\projects\project\project\project4.cpp(22) : see reference to function template instantiation 'void print<std::set<_Kty>
(std::istream_iterator<_Ty>,std::istream_iterator<_Ty> (__cdecl *)(void))>(Container (__cdecl &),std::ostream &)' being compiled

          with

          [

              _Kty=std::string,

              _Ty=std::string,

              Container=std::set<std::string> (std::istream_iterator<std::string>,std::istream_iterator<std::string> (__cdecl *)(void))

          ]

c:\users\admin\documents\visual studio 2010\projects\project\project\project4.cpp(11): error C2039: 'const_iterator' : is not a member of '`global namespace''

c:\users\admin\documents\visual studio 2010\projects\project\project\project4.cpp(11): error C2146: syntax error : missing ';' before identifier 'itr'

c:\users\admin\documents\visual studio 2010\projects\project\project\project4.cpp(11): error C2065: 'itr' : undeclared identifier

c:\users\admin\documents\visual studio 2010\projects\project\project\project4.cpp(12): error C2065: 'itr' : undeclared identifier

c:\users\admin\documents\visual studio 2010\projects\project\project\project4.cpp(12): error C2228: left of '.begin' must have class/struct/union

          type is 'std::set<_Kty> (__cdecl &)'

          with

          [

              _Kty=std::string

          ]

c:\users\admin\documents\visual studio 2010\projects\project\project\project4.cpp(12): error C2065: 'itr' : undeclared identifier

c:\users\admin\documents\visual studio 2010\projects\project\project\project4.cpp(12): error C2228: left of '.end' must have class/struct/union

          type is 'std::set<_Kty> (__cdecl &)'

          with

          [

              _Kty=std::string

          ]

c:\users\admin\documents\visual studio 2010\projects\project\project\project4.cpp(12): error C2065: 'itr' : undeclared identifier

c:\users\admin\documents\visual studio 2010\projects\project\project\project4.cpp(13): error C2065: 'itr' : undeclared identifier



Build FAILED.



Time Elapsed 00:00:01.00

========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
AnthonyW
  • 1,910
  • 5
  • 25
  • 46
  • 2
    How do you call this function? With what arguments? – Nawaz Apr 15 '12 at 17:03
  • The code looks fine. Could it be that you are not calling the `print` function with a container? – juanchopanza Apr 15 '12 at 17:07
  • are your containers containing something that iostream does not understand? so not primitive types? – EdChum Apr 15 '12 at 17:09
  • 1
    Seems to as there is something wrong with the VS compiler. GCC compiles this fine. – Sebastian Apr 15 '12 at 17:16
  • What's the error message VS gives you? – chandsie Apr 15 '12 at 17:17
  • Could you please combine your two code snippets into one? That seems to be basically all the relevant code anyway, so if you show us the whole thing as one (rather than two halves which might or might not be complete if we combine them), we can try running it and see if we can reproduce it – jalf Apr 15 '12 at 17:48
  • Wouldn't it be easier to just write a function that takes in a pair and ostream, then using for_each and a binder? This seems overly complicated if you're just looking to print a set or map. – keelerjr12 Apr 15 '12 at 18:14
  • I would if I could; I copied the above from the book just trying to see how it worked. – AnthonyW Apr 15 '12 at 18:42

2 Answers2

2

It thinks this is a function declaration:

set<string> s(  istream_iterator<string>(fin),
                istream_iterator<string>() );

Adding an extra pair of parentheses will correct it:

set<string> s( (istream_iterator<string>(fin)),
                istream_iterator<string>() );

There are many examples of this on SO if you search for Most Vexing Parse.

Edit: You also need to add #include <string>

Community
  • 1
  • 1
Blastfurnace
  • 18,411
  • 56
  • 55
  • 70
0

Seems like the compilers (also clang++) seem to get confused. The following works for me, though:

#include <iostream>                                                         
#include <set>                                                              
#include <iterator>                                                         
#include <fstream>                                                          

using namespace std;                                                        

template <typename Container>                                               
void print (const Container & c, ostream & out = cout)                      
{                                                                           
    typename Container::const_iterator itr;                                 
    for( itr=c.begin(); itr!=c.end(); ++itr)                                
        out << *itr << " ";                                                 
    out << endl;                                                            
}                                                                           

int main()                                                                  
{                                                                           
    ifstream fin("Test.txt");                                               
    istream_iterator<string> first(fin), last;                              
    set<string> s(first, last);                                             
    print(s);                                                               

    return 0;                                                               
}

However, I would recommend turning your print function into something which accepts an iterator range which which you output using std::copy, as is shown here: http://www.sgi.com/tech/stl/ostream_iterator.html

Michael Wild
  • 24,977
  • 3
  • 43
  • 43
  • I just copy/pasted your code Exactly and I am still getting this `binary'>>'` error I referenced in Mat's post and a whole bunch of similar ones. None of which point to any code in my program itself. – AnthonyW Apr 15 '12 at 18:28
  • I'm sorry, what are your referring to? Is it the `main` function using the `while` loop from your edit? In this thread, no Mat posted anything, and neither did he in the thread about the "Most vexing parse". – Michael Wild Apr 16 '12 at 04:36
  • Mat deleted his post when he gave up. The fix for the error I was referring to is simply to `#include `. Yet the error was so obscure I never would have figured out that That was the problem. – AnthonyW Apr 16 '12 at 04:48
  • Glad you found the error. I also find MSVC error messages to be almost inscrutable. You might want to give [clang](http://clang.llvm.org) a try. It is about the most standards conforming compiler I know and IMHO produces the best error messages (including colours and arrows pointing to the error). – Michael Wild Apr 16 '12 at 07:13
  • I may have to give that a shot; I have been using Eclipse to code android apps and it has allowed me to take for granted simple things like easy-to-follow error messages and one-click imports. If clang is of a similar nature I am sure to soon be a fan. – AnthonyW Apr 16 '12 at 07:36
  • Well, clang is a command-line tool (like all compilers I know of), and as such, it outputs its errors to the command line, but as opposed to other compilers, it does so in a much more readable way. Especially errors in templates are much better diagnosed, and also simple things, like missing semi-colons, are correctly detected instead of reporting an error 10 lines further down... I don't know whether Eclipse CDT has an error parser for clang yet. – Michael Wild Apr 16 '12 at 07:46