Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

g++ 4.6.3 reading contents of a file into string parsing ambiguity

Tags:

c++

g++

I would like to read the contents of a ifstream

#include <vector>
#include <iterator>
#include <fstream>

std::ifstream stream;
std::vector<char> buf(std::istreambuf_iterator<char>(stream),
    std::istreambuf_iterator<char>());

But then when I say:

if(buf.size())
...

I get an error

error: request for member 'size' in 'buf', which is of non-class type 'std::vector<char, std::istreambuf_iterator<char, std::char_traits<char> > >(std::istreambuf_iterator<char, std::char_traits<char> >, std::istreambuf_iterator<char, std::char_traits<char> > (*)())'

So the compiler thinks I am declaring a function instead of a vector<char>. How can I make it work?

I compile with -std=c++0x with g++-4.6.3

This question is more about parsing disambiguation than reading of a file.

like image 835
iggy Avatar asked Apr 24 '15 12:04

iggy


1 Answers

That is why one should use curly braces for initialization:

std::vector<char> buf { 
                        std::istreambuf_iterator<char>(stream),
                        std::istreambuf_iterator<char>() 
                       };

In your case, buf is not an object — it is rather a function declaration. Search for vexing parse in c++ to know the explanation why it is a function declaration.There are pretty much hundreds of topics on this.


Alright. Here is what happens to your code. This code:

 std::vector<char> buf(std::istreambuf_iterator<char>(stream),
                      std::istreambuf_iterator<char>());

is seen by the compiler as function declaration, where:

  • the function name is buf which returnsstd::vector<char>.
  • it takes two parameters of types:
    • std::istreambuf_iterator<char>(stream), which is just another way of writing std::istreambuf_iterator<char> stream (parens are superfluous in this case).
    • std::istreambuf_iterator<char>() which is a function type again (parens are not superfluous in this case) — which decays to a function pointer type, pointing to a function:
      • which takes nothing and return std::istreambuf_iterator<char>

So your code becomes this:

std::vector<char>                         //return-type
buf                                       //function-name
(
  std::istreambuf_iterator<char> stream,  //1st (named) parameter
  std::istreambuf_iterator<char> (*)()    //2nd (unnamed) parameter
);

Hope that helps.

like image 192
Nawaz Avatar answered Oct 29 '22 17:10

Nawaz