I have the following parser class that works in Visual C++
class Parser
{
private:
const char* filename;
std::ifstream filestream;
std::vector<std::string> tokens;
unsigned int linect;
public:
Parser(const char* filename);
bool readline();
std::string getstrtoken(unsigned int i) const { return tokens[i]; }
int getinttoken(unsigned int i) const { return atoi(tokens[i].c_str()); }
};
Parser::Parser(const char* filename) :
filename(filename),
linect(0)
{
filestream = ifstream(filename); // OK in VC++, not with GCC?
}
bool Parser::readline()
{
std::string line;
getline(filestream, line);
std::stringstream ss(line);
std::string token;
tokens.clear();
while(getline(ss, token, ' ')){ if(token != "") tokens.push_back(token); }
linect++;
return (filestream != NULL);
}
But when I try to compile it with GCC 4.8.2, I get errors saying that I cannot assign to filestream
. From what I read elsewhere on this site, you can do
std::ifstream filestream(filename);
but you cannot do
std::ifstream filestream;
filestream = ifstream(filename);
which is essentially what I need to do if I want to declare filestream
as a member of the Parser
class and initialize it in the constructor.
I would like to have the file stream kept within the Parser
class so that those who use the parser don't need to declare and keep track of it. It seems to me that this should be self-contained in the Parser
class since its internal methods (e.g. readline()
) are the only ones that use it.
Is there a way to achieve this that works with both platforms?
Thanks.
edit: My fix was to explicitly call the open()
method of ifstream
. My parser class constructor now looks like:
Parser::Parser(const char* filename) :
filename(filename),
linect(0)
{
filestream.open(filename);
// Do some checking to make sure the file exists, etc.
}
std::ifstream don't have a copy constructor, probably one of the many extensions of VC++. Correct code is:
Please take note of member variable and parameter filename. Use this-> or change name (recommended, normally prefix is used for member variables
_
orm_
)I think a better solution would be for you to:
ifstream
first.Parser
using theifstream
object.Parser
to store a reference to anistream
object. This allows you the flexibility of being able parse the contents of a file, stdin, and a string.You can't, since
std::ifstream
has deleted copy constructor and copy assignment. You may get around by doingThe fact that it compiles on visual studio is mostly because it gets inlined into either move assignment or move constructor(I'm not so good to tell you which exactly). If you try
it won't compile.
However you may try to do the move I wrote, or you can just call
.open
(http://en.cppreference.com/w/cpp/io/basic_ifstream/open)