1

My use case is to create a function which takes a fileName , an ifsttream/ofstream object and then opens the file for reading/writing accordingly in the given filestream object. also to check whether the operation was successful or not and if successful, returns the filestream object.

My implementation is as following and is based on the assumption that both ifstream and ofstream are derived from fstream.

#include <iostream>
#include <fstream>
using namespace std;
void populate_filehandles(const string &inFileName, fstream &filehandle) {
    filehandle.open(inFileName);
    if (!filehandle.is_open()) {
            cout << "input file : " << inFileName << " could not be opened" << endl;
            exit(0);
        }
}
int main () {
    ifstream inFile;
    string inFileName = "abc.txt";
    populate_filehandles(inFileName, inFile);
}

the code gives an error that ifstream can not be converted to fstream. is there any other way to solve the problem?

Vishesh Arya
  • 39
  • 1
  • 10
  • I think it isn'T a good design to handle ofstream and ifstream (if it would possible) in the same function. Maybe with a templated function it will work – RoQuOTriX May 08 '20 at 06:34
  • You are passing the stream into the function by reference, why do you need to return it as well? Just change the function return type to `void`. Now the only prolbem to solve is the error message, at the moment is say "input file" which isn't necessarily true. – john May 08 '20 at 06:36
  • 2
    That code does not produce that message. Please post a [mcve]. – molbdnilo May 08 '20 at 06:42
  • You might want to verify your assumption that both `ifstream` and `ofstream` are derived from `fstream`. Surprises are usually caused by one or more assumptions being mistaken. – molbdnilo May 08 '20 at 07:10
  • @john thanks for the return type suggestion. implemented that. also, i want to check that the filehandle is populated correctly. any reason of that not being the case must be captured. – Vishesh Arya May 08 '20 at 07:10
  • @molbdnilo the reason why i started with this assumption is that all three of these filehandle types are in the same header and by the look of it, if stream and of stream looks like a specialization of fstream. – Vishesh Arya May 08 '20 at 07:13
  • @molbdnilo thanks for your suggestion, i have made the code minimal reproducible. – Vishesh Arya May 08 '20 at 07:13
  • 1
    @VisheshArya Let's make this explicit, `ifstream` inherits from `istream`, `ofstream` inherits from `ostream`, `fstream` inherits from `iostream`. So the code as currently written cannot work. [Reference](https://en.cppreference.com/w/cpp/io) – john May 08 '20 at 07:18
  • @john thanks a lot for the clarification. my apologies for bad assumptions. so is there any way to make a unified function for ifstream and ofstream handles? as apart from their type, the rest of the code is same. or i will need to make 2 separate functions? – Vishesh Arya May 08 '20 at 07:59
  • @VisheshArya Well I made a similar assumption until molbdnilo pointed it out. Two separate functions seems like the simplest solution to me. – john May 08 '20 at 08:40
  • `template void populate_filehandles(const string &inFileName, FileStream &filehandle) {...}` will accept either `ifstream` or `ofstream`, and in fact any object with suitable `open()` and `is_open()` methods. – Igor Tandetnik May 09 '20 at 15:25
  • @IgorTandetnik Thanks a lot Igor. i guess the only way to combine both kinds is through template function. – Vishesh Arya May 22 '20 at 03:39

1 Answers1

0

So, as others have suggested, this is due to the fact that std::ifstream doesn't inherit from std::fstream. Rather, it inherits from std::istresm instead. std::fstream on the other hand inherits from std::iostream. So you can't really do that.

Some options you have to work around:

  1. Templates (as others have mentioned):
template <class T> void populate_filehandles(const string &inFileName, T &filehandle)
  1. Overloading:
void populate_filehandles(const string &inFileName, std::ifstream &filehandle)
void populate_filehandles(const string &inFileName, std::ofstream &filehandle)

This, however will require you to implement the same function twice. Not necessarily the best idea, but would work.

  1. Pass a flag

Something interesting about std::fstream is that it has the ability to open a file for reading or writing (or even both I think). So, in theory, you could add a flag to say which direction you want to open it:

void populate_filehandles(const string &inFileName, fstream &filehandle, bool reading) {
    if(reading) {
        filehandle.open(inFileName, std::ios::in);
    } else {
        filehandle.open(inFileName, std::ios::out);
    }
    //...
}