-1

I want to extend the std::fstream class from the <fstream> header. I plan to add a couple functions like std::fsteam create(path), std::vector<std::string> read_lines(path), etc.

What Im asking is pretty simple. Instead of creating a whole new class, I want to be able to just simply add the methods in another file and then just make std::fstream objects and use those new methods.

I have two files. file_helper.hh where I will declare the methods, and file_helper.cc where I will define them and link them to my main.cc file.

So, what do I write within file_helper.hh to add these new methods to std::fstream if possible? Is it even possible?

14
  • 3
    The c++ language does not support adding methods to a class without modifying it. Inheriting a standard library class is also not a good idea. You could add free functions getting the fstream by reference as a parameter. Commented Nov 3, 2023 at 5:57
  • 3
    You can't add member to any class(after its definition) let alone standard defined class. Commented Nov 3, 2023 at 5:57
  • 1
    Unclear to me what you are trying to achieve... For instance, what would the purpose of your so-called create method be? Compared to e.g. the constructor? Commented Nov 3, 2023 at 5:59
  • 1
    You cannot, and also the STL classes (in general) are also not designed to be inherited from, I think streams are an exception. Commented Nov 3, 2023 at 5:59
  • 3
    Except for a very few exceptions, you enter the land of UB if you try to use a class in the Standard Library as a base class, and add some new functionality to it. The best thing to do is to encapsulate a Standard Library object in a class of your own, and add the new functions there. Use wrappers to expose the methods from the Standard Library object that you want to use as part of the interface of your class. Commented Nov 3, 2023 at 6:00

2 Answers 2

5

The way to do that in C++ is to add your own free-standing functions with the functionality you want:

// stdex.h #include <string> #include <fstream> #include <vector> namespace stdex { std::vector<std::string> read_lines(std::ifstream& self); } 

And then you just use them as you would any function:

// main.cpp #include <fstream> #include <iostream> #include "stdex.h" int main() { std::ifstream file{"foobar.txt"}; for (const auto& line : stdex::read_lines(file)) { std::cout << line << '\n'; } } 
Sign up to request clarification or add additional context in comments.

4 Comments

all this does is take the object as a parameter which isnt what i was trying to do, i wanted to be able to use it like this std::fstream my_file("foobar.txt"); std::cout << my_file.read_lines()[4]; but ive been told above that its not possible.
@itsrxmmy How is that different/better than std::cout << read_lines(my_file)[4]; ?
I just wanted to know if it was possible to do it that way. I already know how to put parameters inside of a function, which is basically all this solution is. Not that its different or better, I just like to play around with C++ and see where certain lines are drawn and how many workarounds there are.
@itsrxmmy I am showing you how what you're trying to achieve is done in C++ idiomatically. If your only argument is "I want this syntax specifically", then I can't help you with that.
0

What you are describing would look something like below. Note though:

  • The functions you've suggested both take a path parameter. Having to create an instance of your fstream to be able to call create(path) or read_lines(path) doesn't make sense. These functions would be much better as free functions.
#include <filesystem> #include <fstream> #include <string> #include <vector> class myfstream : public std::fstream { // inherit from std::fstream public: // make the fstream constructors and assignment operators available using std::fstream::fstream; using std::fstream::operator=; // example implementations of your member functions: std::fstream create(std::filesystem::path path) const { return {path, std::ios::out}; } std::vector<std::string> read_lines(std::filesystem::path path) const { std::vector<std::string> rv(1); if (std::ifstream is(path); is) { for (; std::getline(is, rv.back()); rv.emplace_back()) {} } rv.resize(rv.size() - 1); return rv; } }; 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.