C++ How do I implement this one parameter constructor? - c++

In this project, I have to create a class called Chain. A chain will be a list of values (like an array). The thing is I have to create this chain without the use of the STL library.
Right now, I have to implement this one parameter constructor:
Chain(const Object& item)
{
// Write something.
}
"Object" by the way is just the name of the template for the class.
I have these two private variables as part of the class:
size_t size_;
Object *array_;
Let's say I wanted to make this call from main:
Chain<int> d{7};
That's just saying pass 7 to the one parameter constructor.
How would I go about implementing this one parameter constructor?
Also, I need to be able to print out this class if from main I type for example:
Chain<int> d{7}; // A chain containing 7 should be created.
cout << d; // Should just print [7]
In order to do that, I have to implement this overloaded << operator:
// Overloading the << operator.
friend std::ostream &operator<<(std::ostream &out, const Chain &a_chain)
{
// Print the chain.
return out;
}
Attempted code so far:
// One parameter constructor.
Chain(const Object& item)
{
array_ = new Object[item];
// array_=item;
size_++;
}
// Overloading the << operator.
friend std::ostream &operator<<(std::ostream &out, const Chain &a_chain)
{
cout << array_ << endl;
return out;
}

With these types of things, it's best to take things one step at a time, making sure you've got each small piece working before adding additional complexity. See How to debug small programs for more details.
For the code (now) you've shown, here is code that does exactly what you've described, and nothing more.
template<typename T>
struct Chain
{
T value;
};
// Overloading the << operator.
template<typename T>
std::ostream &operator<<(std::ostream &out, const Chain<T> &a_chain)
{
out << a_chain.value << std::endl;
return out;
}
int main()
{
Chain<int> d{ 7 }; // A chain containing 7 should be created.
std::cout << d; // Should just print [7]
return 0;
}
Note that using Object* array_ isn't necessary to get this snippet of code working. Once you're satisfied with what this does, you can add more pieces. For example, if you really are trying to implement your own std::vector<>-like class (bad idea), your next step might be to remove templates as that's an additional complexity.

Related

how to overload << operator in c++ to use repeatedly?

Sorry for the not clear title.
Recently I started to learn C++ and I don't know how to overload operator << to make it repeatable.
Here's an example code.
class Foo{
private:
int* a;
int idx = 0;
public:
Foo(){a = new int[100];
void operator<< (int a) {arr[idx++] = a;}
What << does is basically class get integer number as an operand and save it into arr.(Ignore overflow case here)
For example, a << 100 will add 100 into array.
What I want to do is make << operator can be repeatedly used inline like a << 100 << 200
How should I fix above code to allow this function?
Thanks in advance :)
The overloaded Foo::operator<<() takes actually two arguments:
The parameter int given as right-hand side
The implicit this from left-hand side.
To allow chaining of this operator, it should return a reference to the left-hand-side (i.e. *this) to become usable at left-hand-side itself.
Sample code:
#include <iostream>
struct Foo {
Foo& operator<<(int a)
{
std::cout << ' ' << a;
return *this;
}
};
int main()
{
Foo foo;
foo << 1 << 2 << 3;
}
Output:
1 2 3
Live demo on coliru
Chaining is enabled by returning a reference to the instance so you can call another method:
class Foo{
private:
std::vector<int> a;
public:
Foo(){}
Foo& operator<< (int a) {
arr.push_back(a);
return *this;
}
};
Now you can call f << 100 << 200 << 42;.
Note that I replaced the array with a std::vector to make Foo less broken (unless you have a descrutor that you did not show it was leaking memory, you could fix that, but then still copying would cause problems, in short you need to respect the rule of 3/5 when you own a resource, using a std::vector makes things much simpler).
PS: Same works for other methods. You simply call another method on the returned reference to this. Note that operators are just methods (with some syntactic sugar) and to see that you can write as well f.operator<<(100).operator<<(200).operator<<(42);.
Return a reference to *this. It's unrelated but you should use a vector to avoid memory leaks. Try to avoid raw new
class Foo{
private:
std::vector<int> a;
public:
Foo &operator<< (int a) {
arr.push_back(a);
return *this;
}
};

What is the correct way to create a function that takes an ostream reference and prints to it?

As the title states, I am trying to make a function that takes an ostream reference and prints to it. The context is that of a Binary Search Tree.
I am not too experienced with ostream, I've only used it once before (only started learning c++ about 3 weeks ago) which I based off a basic template example for operator<< overloading that I found on google.
With my limited understanding I am not sure how I would implement this with a function that I have created.
This is what I've attempted so far based on my limited knowledge,
I first created the reference void write(std::ostream &out) const;
Then I tried to create the function,
std::ostream& write(std::ostream &out,node& o){
out << o.leftChild<< " " << o.val << " " << o.rightChild;
return out;
}
i.e. o.leftChild and o.rightChild should print the results of the node. o.val is just the data in the node.
The expected results should be something like 1 2 3 4. However, if I attempt to use the reference as I did above, I am given an error message by my IDE saying that write was not implemented.
However if I wrote the reference as a method, the results are returned as blank.
UPDATE: Removed what I assumed was the reference, and I no longer get any error messages.
However result is still zero, which I assume is because of my incorrect implementation.
UPDATE2:
What I am trying to attempt precisely, is to have the write function print to it,
The result of calling write on the left child, followed by a space, data from the node, a space and the the result of calling write on the right child (if there is one).
All prior code to this segment I've shown works as intended. For the variables, data is a template argument type (T), the left and right childs are unique_ptr<node>s.
Your first write() declaration is declaring a method in a class (presumably the node class), but you are not implementing the body of that method. That is what the compiler is complaining about.
Your second write() is implementing the body of a standalone function, not the class method.
Try something more like this instead:
class node {
...
public:
...
void write(std::ostream &out) const;
};
void node::write(std::ostream &out) const {
if (leftChild) {
leftChild->write(out);
out << " ";
}
out << val;
if (rightChild) {
out << " ";
rightChild->write(out);
}
}
Which can then be used like this:
node n;
...
n.write(std::cout);
unique_ptr<node> n(...);
...
n->write(std::cout);
If you want to implement a standalone function, it would look more like this:
class node {
...
public:
...
void write(std::ostream &out) const;
};
std::ostream& write(std::ostream &out, const node &n);
void node::write(std::ostream &out) const {
...
}
std::ostream& write(std::ostream &out, const node &n) {
n.write(out);
return out;
}
Which can then be used like this:
node n;
...
write(std::cout, n);
unique_ptr<node> n(...);
...
write(std::cout, *n);
And then you could take it a step further by changing the standalone function into a custom operator<< instead:
class node {
...
public:
...
void write(std::ostream &out) const;
};
std::ostream& operator<<(std::ostream &out, const node &n);
void node::write(std::ostream &out) const {
if (leftChild)
out << *leftChild << " ";
out << val;
if (rightChild)
out << " " << *rightChild;
}
std::ostream& operator<<(std::ostream &out, const node &n) {
n.write(out);
return out;
}
node n;
...
std::cout << n;
unique_ptr<node> n(...);
...
std::cout << *n;
First thing: void write(std::ostream &out) const; is NOT reference. It is declaration of a function.
Second: judging from const at the end of declaration it is method inside the class. Then you have to use scope operator (::) while defining method outside class body.
As for "blank results" nothing can be said without more code.

How to use osstream properly in c++. Is there a easy or better way of implementing logging of program execution flow to a file in c++

While trying to work with the << operator and std::basic_ostream, I ran into an error and I don't understand why it's a problem.
In the code samples below, the 1st statement works for both version but the 2nd statement only works with version 1
*TestLog::getInstance() << "Hi this is ";
*TestLog::getInstance() << "Hi this is " << endl;
What exactly happens if we overload the operator << std::basic_ostream?.
Version 1
ofstream logFile("log.txt")
class TestLog : public std::basic_ostream<char, std::char_traits<char> >
{
public:
static TestLog* getInstance()
typedef std::basic_ostream<char,std::char_traits<char> > SuperType;
TestLog& operator<<(SuperType& (*manip)(SuperType& ))
{
stream1_ << manip;
return *this;
}
template<typename T>
TestLog& operator<<(const T& t)
{
stream1_ << t;
return *this;
}
protected:
TestLog();
private:
static TestLog* _instance;
std::ostream& stream1_;
};
TestLog* TestLog::getInstance()
{
if(_instance == 0)
{
_instance = new TestLog();
}
return _instance;
}
TestLog::TestLog():SuperType(logFile.rdbuf()), stream1_(logFile)
{
}
Version 2
class TestLog
{
public:
static TestLog* getInstance()
template<typename T>
TestLog& operator<<(const T& t)
{
stream1_ << t;
return *this;
}
protected:
TestLog();
private:
static TestLog* _instance;
std::ostream& stream1_;
};
TestLog* TestLog::getInstance()
{
if(_instance == 0)
{
_instance = new TestLog();
}
return _instance;
}
TestLog::TestLog():stream1_(logFile)
{
}
The statements as posted all "work" with both approaches shown. I guess you meant to use a manipulator like std::flush (maybe even std::endl which shouldn't be used anyway) instead of "a test" for the second statement as that would, indeed, only work with the first apporoach: std::flush is a function template whose type needs to be deduced upon use. Since your [misguided] implementation of the output operator itself is a template the template arguments for std::flush cannot be deduced and the compilation fails. In the first approach your class contains an explicit overload dealing with the type of a template instantiation of the manipulators which is sufficient to deduce the necessary template argument.
Either way, your approach to creating a new stream is not a good idea at all! Both of your approaches fail, e.g., when trying to pass the resulting "stream" to something which expects and std::ostream& as argument. For output streams there are two independent dimensions which can vary (similarly for input streams):
For any new type objects can be formatted in a specific way. This is done by overloading the shift operator for std::ostream& and the object's type.
The destination of characters can be modified. This is done by inheriting from std::streambuf and overriding the appropriate virtual function, notably overflow().
Your code tries to change the destination of characters by overloading the shift operator. Doing so is not intended to work and does create subtle problems like the problem not working with manipulators, functions taking std::ostream& as argument, or attempts to change the format flags of the "stream" using the various accessor functions.

Why is my overloaded << operator not working?

I'm trying to understand how to properly overload the "<<" operator so that I can use
std::cout << my_object;
to print useful debug messages. In particular, I need to have an implementation of << for each of my subclasses, so I'm declaring << to be virtual in the superclass.
Right now I'm stuck with the following piece of code
#include <iostream>
using namespace std;
class Shape {
public:
virtual ~Shape() { };
virtual ostream& operator<<(std::ostream &strm) = 0;
};
class Square : public Shape {
int size;
public:
Square() { size = 10; }
~Square() { }
ostream& operator<<(std::ostream &strm) {
return strm << "a square with size " << size;
}
};
int main() {
Square *my_square = new Square();
cout << "my_square is " << my_square << "\n";
}
which (I think) should be working, but doesn't. What I get when using "<<" is that the pointer value of my_square gets printed, rather than the result of the overloaded << .
$ ./a.out
my_square is 0xcacc20
What am I missing here?
operator<< can't be a member function. This is because of the order of the arguments. The stream has to come first.
When calling an overloaded operator, such as:
os << object;
the compiler will attempt to look up both
os.operator<<(object);
and
operator<<(os, object);
(The rules for this can be rather complex, I won't attempt to describe them here.)
Because the stream always comes on the left, your member function will never be found, since it would have to be called as:
object.operator<<(os);
You need to write a free function like:
ostream& operator<<(std::ostream &strm, Square const& square) {
return strm << "a square with size " << square.size();
}
(where Square::size() returns the size member).
Then you need to remember to dereference your pointer too:
std::cout << *my_square << '\n';
Although I see no reason to be dynamically allocating my_square in this example anyway. Just stick it on the stack as a local variable.
If the aim here is ultimately to be able to print any Shape&, and have the printed output follow the "real" type, you would need to create:
virtual std::ostream& print(std::ostream&) const = 0;
in the Shape base class, and override it in each derived class, then have a free function:
std::ostream& operator<<(std::ostream& os, Shape const& shape)
{
return shape.print(os);
}
It is often advised to make all binary operators on your type non-member functions, so that both arguments are treated equally, and the operation remains commutative. See Scott Meyers, Effective C++ (3rd Edition), Item 24, (or find a summary online).
As noted by others, the problem is that operator << can't be member function (because of the order of arguments). The canonical way to do this is to have operator <<(const Shape&) call a virtual function in Shape
class Shape {
friend ostream& operator<<(std::ostream& str, const Shape& shape);
virtual void do_print(ostream& str) = 0;
public:
virtual ~Shape() { };
};
ostream& operator<<(std::ostream& str, const Shape& shape) {
shape.do_print(str);
return str;
}
Note that it is legal to have do_print be private, even though it is going to be (must be) overridden by derived classes. You could make it protected though if you like.
What am I missing here?
You have created operator which will get you class as a first argument and stream as the second.
my_square << std::cout;
I'd create free function and to make it dynamic I'd call some virtual method in it

C++: Overloading << operator with function pointers

I have a class "stampstream" that is essentially intended to work like 'cout'. The two functions that follow are outside the class. This is the part that works.
class stampstream: public std::ostream
{
//code
stampstream& operator<<(stampstream& (*x)(void))
{
//code
}
//code
};
stampstream& endr()
{
//nocode
}
stampstream& (*endrow)(void)=endr;
In main:
stampstream s;
s << "teststring1" << endrow;
Note that "endrow" is essentially 'endl'. This part works perfectly fine, compiles and executes with the right output.
Now, I'm trying to overload << with another possible row(int) function. This is the part that doesn't work. Again, it's part of the same class as above and the following 2 functions are outside the class.
class stampstream: public std::ostream
{
//code
stampstream& operator<<(stampstream& (*r)(int y))
{
//code
}
//code
};
stampstream& ro(int y)
{
//nocode
}
stampstream& (*row)(int)=ro;
In main:
s << "teststring2" << row(5);
This is the error I get:
error: invalid user-defined conversion from ‘stampstream’ to ‘stampstream& (*)(int)’ [-fpermissive]
What am I doing wrong with row ?
The problem is that in
s << "teststring2" << row(5);
function call has higher precedence than <<, so this calls the function row points at and then tries to pass its return value (a stampstream &) to operator<<.
What you want is
s << "teststring2" << row;
This doesn't call the function and instead passes the pointer to operator<<. Inside that function, when you want to call x, you'll need to provide the argument.
It sounds like what you are trying to do is to have a function row that creates a functor object that you can then pass to operator<<. You can do that in C++11 with a lambda:
class stampstream: public std::ostream
{
//code
stampstream& operator<<(std::function<stampstream&(void)> r)
{
//code
}
//code
};
std::function<stampstream&(void)> row(int x)
{
return [x]()->stampstream & {
//code
}
}
Which you can call as:
s << "teststring2" << row(5);
The call to row happens first, which constructs a lambda and returns it (but doesn't yet run the code in it). The functor is passed to operator<< and when that function calls r, it will call the code in the lambda (which can refer to the x param, which was bound by value, so copied into the lambda.)
Since Chris has already answered your question, I wanted to advise you of alternatives to your current method:
Your stampstream class should use a specialized std::streambuf that writes out the stamp inside overflow(). There's no need to extend an std::ostream and reimplement the input operators. For an example of how to do this, see this thread.
You seem to be using endrow and row like manipulators. Operator overloads already exist for manipulators that do not take arguments at the call site. You can have endrow take and return an object of type std::ostream&. For row you can have it return a class that overloads the inserter to allow the syntax you want:
struct row_impl
{
row_impl(int row) : row(row) { }
// Write out the row and return the stream
friend std::ostream& operator<<(std::ostream& os, row_impl const& rimpl);
private:
int row;
};
std::ostream& operator<<(std::ostream& os, row_impl const& rimpl)
{
// This is where the code for your original row() function goes
}
// write out to and return the stampstream instance
std::ostream& endrow(std::ostream& os);
row_impl row(int row)
{
return row_impl(row);
}
Now s << endrow and s << row(5) will work without having to add anything to your stampstream class.