5

In the code snippet below, if I exclude the parenthesis around the second call to std::istreambuf_iterator, I get a compile error on the last line:

left of .c_str() must have a class/struct/union.

std::ifstream file("file.txt");;

std::string prog(
    std::istreambuf_iterator<char>(file),
    (std::istreambuf_iterator<char>()));
prog.c_str();

What do these parentheses actually do? It seems to me that they should be able to be excluded.

  • Your instinct is good: they shouldn't be needed. But they are. As @LuchianGrigore says, it's to avoid the "most vexing parse", which is a bit of a glitch in the C++ grammar. – Pete Becker Sep 11 '12 at 18:34
  • If you remove the parentheses, does `std::istreambuf_iterator()` represent a function call, or an inline object instantiation? That is the ambiguity the compiler sees, and thus the error. – Steve Guidi Sep 11 '12 at 18:34
  • 1
    possible duplicate of [Vector constructor with two parameters is parsed as a function declaration](http://stackoverflow.com/questions/8927939/vector-constructor-with-two-parameters-is-parsed-as-a-function-declaration) Exactly the same issue, just with vector instead of string. – jrok Sep 11 '12 at 18:43

1 Answers1

6

Without the parenthesis, this would be a case of most vexing parse. It wouldn't declare a variable, but a function returning a std::string, called prog and taking those two types as parameters. If you attempt to call it afterwards, you'll get a linker error.

Luchian Grigore
  • 253,575
  • 64
  • 457
  • 625
  • @DavidRodríguez-dribeas The thing is, I have no idea why. I gathered this is the cause from the error message :) If you (or anyone else) can explain, I'll remove this answer. – Luchian Grigore Sep 11 '12 at 18:34
  • +1: didn't even know that had a name! only happens to you once :P – QuantumKarl Sep 11 '12 at 18:35
  • 3
    It can be parsed as a function taking a first argument of type `std::istreambuf_iterator` with name `file` (i.e. the parenthesis around `file` are optional, as in `int (a) = 5;`) and a second argument of type function pointer (after the decay) taking no arguments and returning a `std::istreambuf_iterator`, this argument being unnamed. That is, it is equivalent to a declaration: `typedef std::istreambuf_iterator it; std::string prog( it file, it (*)() );` – David Rodríguez - dribeas Sep 11 '12 at 18:37
  • @DavidRodríguez-dribeas ah, true. The `(file)` confused me. :) – Luchian Grigore Sep 11 '12 at 18:38