Kevin Truong
Kevin Truong

Reputation: 39

Initializing Constructors for istream vs file path

I'm trying to write a class that reads a file or input but I'm having trouble figuring out the constructors. I want a constructor that reads a file name and one that reads from an istream.

I'm not sure if that makes sense so I'll add my code if it helps.

main.cc:

#include "Doc.h"
#include <cassert>
#include <stream>
#include <iostream>
#include <string>

using namespace std;

int main() {
    // Read from file
    Doc document("romeo.txt");

    // Read from stream
    ofstream("data") << "\r \r  \n\nPeter  \n   Ray\r \n  Egon  \n \n\r\n";
    Doc d("data");
    return 0;
}

Doc.h:

#ifndef DOCUMENT_H
#define DOCUMENT_H

#include <iostream>
#include <string>

class Doc {
  public:
    Doc();                              // Default Constructor
    Doc(const Doc &);                   // Copy Constructor
    ~Doc();                             // Destructor
    Doc& operator=(const Doc &);        // Assignment Constructor

    // File path constructor
    Doc(std::string file_path);              // Doc(path)
    // Istream constructor
    Doc(std::istream& input);                 // Doc(istream)
}

Upvotes: 1

Views: 300

Answers (1)

Matt Cummins
Matt Cummins

Reputation: 324

You can use a delegating constructor (C++11) to have the file path constructor call the istream constructor:

Doc(const std::string& file_path)
    : Doc{std::ifstream{file_path}} // Creates an istream from the file
{}

EDIT: As pointed out, this won't work because the istream constructor takes it by reference, to get around this you could have both constructors delegate to a private function that reads from a stream like so

class Doc {
    void load_from_stream(std::istream& stream);

public:
    Doc(const std::string& file_path) {
        auto stream = std::ifstream{file_path};
        load_from_stream(stream);
    }

    Doc(std::istream& stream) {
        load_from_stream(stream);
    }
};

Upvotes: 2

Related Questions