Reputation: 2022
I try to compile simple program
int main(int argc, char* argv[]) {
std::ifstream strings(std::string(argv[1]));
std::string line;
while (!strings.eof()) {
strings >> line;
}
}
and get peculiar error:
error: request for member ‘eof’ in ‘strings’, which is of non-class type ‘std::ifstream(std::string*) {aka std::basic_ifstream<char>(std::basic_string<char>*)}’
if I change to
std::ifstream strings(argv[1]);
all compiles well.
What happens here? Compiler is gcc 4.7 and 4.9.
Upvotes: 0
Views: 122
Reputation: 254621
This is sometimes known as the most vexing parse: the declaration of strings
is interpreted as a function declaration, taking a pointer (expressed as an array) as its argument. To make this clearer, I'll remove some parentheses which are redundant in a function declaration:
std::ifstream strings(std::string argv[1]);
which, by the ancient rules of array/pointer confusion, is equivalent to
std::ifstream strings(std::string * argv);
which matches the type mentioned in the error message.
Since C++11, you can resolve this using brace-initialisation:
std::ifstream strings{std::string(argv[1])};
^ ^
In historical dialects, you would need more verbosity:
std::ifstream strings = std::ifstream(std::string(argv[1]).c_str());
Note that, before C++11, you couldn't pass a std::string
directly to the constructor, but would need c_str()
to get a C-style string.
As you say, you can simply pass argv[1]
as the argument in any C++ dialect, avoiding the vexatious parse entirely.
Upvotes: 4