Краткий ответ - сначала создать свой объект ifstream и передать его как ссылку на ваш синтаксический анализатор. Не забудьте искать поток обратно в начало, прежде чем покинуть свою функцию или когда вы начнете читать.
RAII должен создать объект-оболочку, который автоматически делает это, когда выходит из области видимости.
class ifStreamRef{
ifStreamRef(std::ifstream& _in) : mStream(_in){}
~ifStreamRef(){mStream.seekg(0);}
std::ifstream& mStream;
}
Затем вы создаете экземпляр оболочки при вводе метода, который будет читать fstream.
void read_value(std::ifstream& input, ...){
ifStreamRef autoRewind(input);
}
Или, поскольку Ctor может выполнять преобразование ...
void read_value(ifStreamRef streamRef, ...) {
streamRef.mStream.getLine(...);
}
std :: ifstream сам следует RAII, поэтому он закроет () поток для вас, когда ваш поток выйдет из области видимости.
Длинный ответ заключается в том, что вы должны прочитать о внедрении зависимости. Не создавайте зависимости внутри объектов / функций, которые могут быть общими. Есть много видео и документов по внедрению и инверсии зависимостей.
По сути, создайте объекты, от которых зависят ваши объекты, и передайте их в качестве параметров.
Внедрение теперь зависит от интерфейса объектов, которые вы передаете. Поэтому, если вы измените свой класс ifStreamRef, чтобы он действовал как интерфейс:
class ifStreamRef{
ifStreamRef(std::ifstream& _in) : mStream(_in){}
~ifStreamRef(){mStream.seekg(0);}
std::string getLine(){
// todo : mStream.getLine() + return "" on error;
}
bool eof() { return mStream.eof(); }
std::ifstream& mStream;
}
Затем вы можете изменить внутреннюю реализацию, которая будет принимать ссылку на vector<string>&
вместо ifstream
...
class ifStreamRef{
ifStreamRef(std::vector<string>& _in) : mStream(_in), mCursor(0){}
~ifStreamRef(){}
std::string getLine(){
// todo : mStream[mCursor++] + return "" on error;
}
bool eof() { return mCursor >= mStream.size(); }
std::vector<string>& mStream;
size_t mCursor;
}
Я упростил несколько вещей.