Reputation: 3866
For some reason, when I try to use std::endl with my OutputStream object, it prints '1' both on-screen and in the file!! (I think it is actually trying to print the OutputStream object itself, but I could be wrong.) Here is my code:
OutputStream.h
#ifndef OUTPUTSTREAM_H
#define OUTPUTSTREAM_H
#include <fstream>
#include <iostream>
#include <string>
class OutputStream : public std::ostream
{
public:
OutputStream(const std::string&);
virtual ~OutputStream();
//template <typename T> OutputStream& operator<<(T);
template <typename T> OutputStream& operator<<(T& data)
{
std::cout << data;
*(this->file) << data;
return *this;
}
template <typename T> OutputStream& operator<<(const T& data)
{
std::cout << data;
*(this->file) << data;
return *this;
}
void changeDestinationTo(const std::string&);
std::string getDestination() const;
// overloading the endl operator to allow for the same functionality that exists on other ostream objects, and returning
// the same type allows for cascading calls
static OutputStream& endl(OutputStream&);
protected:
private:
std::string filename;
std::ofstream * file;
};
#endif // OUTPUTSTREAM_H
OutputStream.cpp
#include "OutputStream.h"
#include <iostream>
#include <fstream>
#include <new>
#include <string>
OutputStream::OutputStream(const std::string& theFileName)
{
// specify the filename
this->filename = theFileName;
// open the fileName with that file
this->file = new(std::nothrow) std::ofstream(this->filename.c_str());
}
OutputStream::~OutputStream()
{
// delete the file! (no, not really)
this->file->close();
delete this->file;
}
/*template <typename T>
OutputStream& OutputStream::operator<<(T)
{
std::cout << data;
*(this->file) << data;
return *this;
}
template <typename T>
OutputStream& OutputStream::operator<<(T& data)
{
std::cout << data;
*(this->file) << data;
return *this;
}
// the const-correct version of the above function
template <typename T>
OutputStream& OutputStream::operator<<(const T& data)
{
// writing the data to std::cout
std::cout << data;
// writing the data to the file that we specify
*(this->file) << data;
return *this;
}
*/
void OutputStream::changeDestinationTo(const std::string& newFileName)
{
// close the currently-open file
this->file->close();
// open up the file at newFileName
this->filename = newFileName;
this->file->open(newFileName.c_str());
}
std::string OutputStream::getDestination() const { return this->filename; }
OutputStream& OutputStream::endl(OutputStream& myStream)
{
// call std::endl on both std::cout and *(this->file)
std::cout << std::endl;
*(myStream.file) << std::endl;
// allow for cascading by returning myStream
return myStream;
}
main.cpp
#include "Array.h"
#include "OutputStream.h"
#include <iostream>
using namespace std;
int main()
{
// setup the OutputStream
OutputStream outputter("file.txt");
// do some stuff with it
outputter << "This is a test to make sure that it works.\n";
outputter << "25 + 3.7 == " << 25 + 3.7 << '\n'; // doesn't print '1'
outputter << "\nNow testing this with objects:\n" << OutputStream::endl; // prints '1'
// declare an Array of 10 ints
Array<int> someArray(10);
// output them
outputter << "Printing an Array:\n";
outputter << someArray << OutputStream::endl;
return 0;
}
Is there any way to readily remedy this?? (I have tried declaring a friend std::ostream& operator<<(std::ostream& standardStream, const OutputStream& myOutputStream) { return standardStream; }
but that did NOTHING to solve the problem...
Upvotes: 0
Views: 95
Reputation: 995
Try overloading the operator<<
to accept pointers to methods as an argument.
A second option is to create a new class within OutputStream called (for example) endl (similar to the way done to define class specific exceptions) like so:
class endl{}
after that all you need to do is to make operator<< support this type of class:
OutputStream& operator<<(OutputStream::endl& endl){
cout << endl;
*flie << endl;
return *this;
}
and using it like this:
outputer << "some string" << endl();
Upvotes: 0
Reputation: 3866
I was trying to pass a function pointer (endl) to operator<<. That is, I was trying to "print" a function pointer (an address). It worked because I have defined that function to do its job.
Upvotes: 0
Reputation: 96810
I believe you need to create an overload for function pointers (manipulators) like this:
template<typename T>
OutputStream& operator<<(std::ostream& (*manip)(std::ostream&))
{
manip(*this->file);
manip(std::cout);
return *this;
}
Upvotes: 1