c++ templates and overloading operators - c++

I am trying to understand how this program works. i am new to c++ templates.
Can someone explain why we need the following function?
friend std::ostream &operator <<(std::ostream &os, const Temp &temp)
It seems to work only for the string template.
Also, what does the function operator T() {return val;} do?
#include <iostream>
#include<string>
template <typename T>
class Temp {
friend std::ostream &operator <<(std::ostream &os, const Temp &temp) {
os << temp.val;
return os;
}
public:
Temp(T val) : val(val) {}
operator T() {return val;}
public:
T val;
};
usage example:
#include <iostream>
#include<string>
#include "temp2.h"
using namespace std;
int main() {
temp<int> si = 10;
cout << "si: " << si << endl;
si = si + 2;
cout << "After si = si + 2: " << si << endl;
Temp<double> si2 = 15.5;
cout << "si: " << si2 << endl;
si2 = si2 + 2.3;
cout << "After si = si + 2: " << si2 << endl;
Temp<string> ss = string("Hello");
cout << "ss: " << ss << endl;
ss = string(ss).substr(1);
cout << "After ss = si.substr(1): " << ss << endl;
return 0;
}

It's not that the operator << is really needed, but it's convenient to have it when using output streams. Also, the operator needs to access the inner value of the Temp class, hence the friend qualifier. Without it, the class would have to expose the inner value val to the external world somehow (the usual way is to make a public read only method), and this create a maintenance problem, since future evolutions of the class would have to keep supporting the method, even if the class internals change.
In other words, having the << operator declared as friend to the class prevents the implementation details to leak out to the rest of the world.
That said, the T() operator provides almost the service of the hypothetic read only method that I described above, but with replacing the read only part by copying the val field. Basically, it's a cast operator allowing to implicitely cast a Temp value to a T value. The << operator could have been implemented using that cast operator, and thus without the need of the friend qualifier. However, certainly for efficiency concerns, the friend qualifier has been kept to avoid the overhead of copying val.
Regarding the implementation of the << operator, we can see that it rely on the same operator defined for the T typename. Any type having this operator defined for should work without problem with this template.

Related

How to print out a vector which holds objects?

This question stems from a larger code I am working on but hopefully I can break it down to simplify:
Say I have two classes, one which holds 2 integer variables, and another which contains a vector that holds the first class
class TwoInts {
int num1;
int num2;
}
class NumHold {
std::vector<TwoInts> numVector;
}
How would I go about printing my numHold class exactly? I know I would have to provide an overloaded stream operator
std::ostream &operator<< (std::ostream &out, const NumHold &myNumHold){;}
But I'm a little confused as to the syntax regarding how I would print out these integers from the vector. I also understand that in order for the stream operator to work I would have to add it to my class as a friend, I just wanted to keep my NumHold class as simplified as possible for the examples sake. Hopefully this was clear enough of an explanation, any help is appreciated
Treat out how you would treat std::cout, then return it at the end of the function:
std::ostream& operator<<(std::ostream& out, const NumHold &myNumHold){
//one possible output format
for(const auto& twoInt : myNumHold.numVector){
out << twoInt.num1 << ", " << twoInt.num2 << '\n'; //pretend out is std::cout
}
return out; //don't forget to return it at the end
}
If appropriate, declare the overload as a friend function within the NumHold class:
#include<iostream>
class NumHold {
private:
std::vector<TwoInts> numVector;
public:
//friend operator overload declaration
friend std::ostream& operator<<(std::ostream& out, const NumHold& myNumHold);
};
In your example, it is appropriate, as the overload function accesses private variables.
You need to be able to access the members of each TwoInts in order to print them. One way to do this is to make them public.
class TwoInts {
public: //lets NumHold access variables to print
int num1;
int num2;
};
class NumHold {
public:
std::vector<TwoInts> numVector;
friend std::ostream& operator << (std::ostream& out, const NumHold& myNumHold) {
for (const TwoInts& ti : myNumHold.numVector) {
out << "(" << ti.num1 << ", " << ti.num2 << ")" << std::endl;
}
return out;
}
};
You can also consider adding printing methods to your classes:
#include<iostream>
class TwoInts {
private:
int num1;
int num2;
public:
void printnum1(){
std::cout << num1;
}
void printnum2(){
std::cout << num2;
}
}
class NumHold {
private:
std::vector<TwoInts> numVector;
public:
//this function prints the private attributes of the class
void printnumVector(){
for (int i = 0; i < numVector.size(); i++){
std::cout << numVector[i].printnum1() << " " << numVector[i].printnum2() << std::endl;
}
}
};

overloading operator << c++, I am trying to cout the element of class

I am writing this code
ostream& operator <<(ostream& out, Box& B){
return B.l +" "+B.b +" "+B.h +endl;
};
The error I get is
Solution.cpp:40:46: error: ‘std::ostream& Box::operator<<(std::ostream&, Box&)’ must have exactly one argument ostream& operator <<(ostream& out, Box& B){ ^
can someone explain what's wrong? I dont understand.
thanks for your help :)
It seems you mean the following
std::ostream & operator <<( std::ostream& out, const Box& B) {
return out << B.l << " " << B.b << " " << B.h;
}
provided that all used in the operator data members are public data members of the class Box. The operator shall be declared and defined outside the class definition.
If one of the used data members is a private data member of the class then the function should be a friend function of the class and shall be declared (and may be defined) in the class definition. For example
class Box
{
//...
friend std::ostream & operator <<( std::ostream& out, const Box& B) {
return out << B.l << " " << B.b << " " << B.h;
}
//...
};
Pay attention to that it is better to remove in the return statement the operand std::endl. In this case 1) the operator will be more flexible because you can output additional information in the same line and 2) this statement
std::cout << box;
will not confuse readers of the code because they will not see the operand std::endl.
Without this operand in the operator definition in the caller of the operator you can write
std::cout << box << std::endl;
and this statement more clear expresses the intention of the programmer.
It should probably be:
std::ostream& operator<<(std::ostream& out, Box const& B){
out << B.l << " " << B.b << " " << B.h << std::endl;
return out;
};
Full code should look like:
#include <iostream>
class Box {
int l;
int b;
int h;
friend std::ostream& operator<<(std::ostream& out, Box const& B);
};
std::ostream& operator<<(std::ostream& out, Box const& B){
out << B.l << " " << B.b << " " << B.h << std::endl;
return out;
}
int main() {
return 0;
}
Demo
To output a type T to std::ostream, you have to declare standalone operator, which returns reference to that stream
std::ostream& operator<<(std::ostream& out, const T& B)
{
out << B.l << " " << B.b << " " << B.h << '\n';
return out;
}
This operation cannot be member operator because member operator use their class as first argument, therefore it might be necessary declare it as a friend of class T.
Avoid using endl in such operators if not extremely necessary, that manipulator calls out.flush(). If you want new line added, use new-line character.

Are there better ways to overload ostream operator<<?

Suppose that you have the following code:
#include <iostream>
template <typename T>
class Example
{
public:
Example() = default;
Example(const T &_first_ele, const T &_second_ele) : first_(_first_ele), second_(_second_ele) { }
friend std::ostream &operator<<(std::ostream &os, const Example &a)
{
return (os << a.first_ << " " << a.second_);
}
private:
T first_;
T second_;
};
int main()
{
Example example_(3.45, 24.6); // Example<double> till C++14
std::cout << example_ << "\n";
}
Is this the only way to overload the operator<<?
friend std::ostream &operator<<(std::ostream &os, const Example &a)
{
return (os << a.first_ << " " << a.second_);
}
In terms of performance, is it the best way to overload it or are there better options to do this implementation?
I believe that the comments have answered your question well enough. From a pure performance standpoint, there likely is no "better" way to overload the << operator for output streams because your function is likely not the bottleneck in the first place.
I will suggest that there is a "better" way to write the function itself that handles some corner cases.
Your << overload, as it exists now, will 'break' when trying to perform certain output formatting operations.
std::cout << std::setw(15) << std::left << example_ << "Fin\n";
This does not left align your entire Example output. Instead it only left aligns the first_ member. This is because you put your items in the stream one at a time. std::left will grab the next item to left align, which is only a part of your class output.
The easiest way is to build a string and then dump that string into your output stream. Something like this:
friend std::ostream &operator<<(std::ostream &os, const Example &a)
{
std::string tmp = std::to_string(a.first_) + " " + std::to_string(a.second_);
return (os << tmp);
}
It's worth noting a few things here. The first is that in this specific example, you will get trailing 0's because you don't get any control over how std::to_string() formats its values. This may mean writing type-specific conversion functions to do any trimming for you. You may also be able to use std::string_views (to gain back some efficiency (again, it likely doesn't matter as the function itself is probably still not your bottleneck)), but I have no experience with them.
By putting all of the object's information into the stream at once, that left-align will now align the full output of your object.
There is also the argument about friend vs. non-friend. If the necessary getters exist, I would argue that non-friend is the way to go. Friends are useful, but also break encapsulation since they are non-member functions with special access. This gets way into opinion territory, but I don't write simple getters unless I feel that they are necessary, and I don't count << overloads as necessary.
As I understand, the question poses two ambiguity points:
Whether you are specifically aiming at templated classes.
I will assume the answer is YES.
Whether there are better ways to overload the ostream operator<< (as compared to the friend-way), as posted in the title of the question (and assuming "better" refers to performance), or there are other ways, as posted in the body ("Is this the only way..."?)
I will assume the first, as it encompasses the second.
I conceive at least 3 ways to overload the ostream operator<<:
The friend-way, as you posted.
The non-friend-way, with auto return type.
The non-friend-way, with std::ostream return type.
They are exemplified at the bottom.
I ran several tests. From all those test (see below the code used for that), I concluded that:
Having compiled/linked in optimize mode (with -O3), and looping 10000 times each std::cout, all 3 methods provide essentially the same performance.
Having compiled/linked in debug mode, without looping
t1 ~ 2.5-3.5 * t2
t2 ~ 1.02-1.2 * t3
I.e., 1 is much slower than 2 and 3, which perform similarly.
I wouldn't know if these conclusions apply across systems.
I wouldn't know either if you might be seeing behavior closer to 1 (most likely), or 2 (under particular conditions).
Code to define the three methods to overload operator<<
(I have removed default constructors, as they are irrelevant here).
Method 1 (as in the OP):
template <typename T>
class Example
{
public:
Example(const T &_first_ele, const T &_second_ele) : first_(_first_ele), second_(_second_ele) { }
friend std::ostream &operator<<(std::ostream &os, const Example &a)
{
return (os << a.first_ << " " << a.second_);
}
private:
T first_;
T second_;
};
Method 2:
template <typename T>
class Example2
{
public:
Example2(const T &_first_ele, const T &_second_ele) : first_(_first_ele), second_(_second_ele) { }
void print(std::ostream &os) const
{
os << this->first_ << " " << this->second_;
return;
}
private:
T first_;
T second_;
};
template<typename T>
auto operator<<(std::ostream& os, const T& a) -> decltype(a.print(os), os)
{
a.print(os);
return os;
}
Method 3:
template <typename T>
class Example3
{
public:
Example3(const T &_first_ele, const T &_second_ele) : first_(_first_ele), second_(_second_ele) { }
void print(std::ostream &os) const
{
os << this->first_ << " " << this->second_;
return;
}
private:
T first_;
T second_;
};
// Note 1: If this function exists, the compiler makes it take precedence over auto... above
// If it does not exist, code compiles ok anyway and auto... above would be used
template <typename T>
std::ostream &operator<<(std::ostream &os, const Example3<T> &a)
{
a.print(os);
return os;
}
// Note 2: Explicit instantiation is not needed here.
//template std::ostream &operator<<(std::ostream &os, const Example3<double> &a);
//template std::ostream &operator<<(std::ostream &os, const Example3<int> &a);
Code used to test performance
(everything was placed in a single source file with
#include <iostream>
#include <chrono>
at the top):
int main()
{
std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now();
std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now();
const int nout = 10000;
Example example_(3.45, 24.6); // Example<double> till C++14
begin = std::chrono::steady_clock::now();
for (int i = 0 ; i < nout ; i++ )
std::cout << example_ << "\n";
end = std::chrono::steady_clock::now();
const double lapse1 = std::chrono::duration_cast<std::chrono::microseconds>(end - begin).count();
std::cout << "Time difference = " << lapse1 << "[us]" << std::endl;
Example2 example2a_(3.5, 2.6); // Example2<double> till C++14
begin = std::chrono::steady_clock::now();
for (int i = 0 ; i < nout ; i++ )
std::cout << example2a_ << "\n";
end = std::chrono::steady_clock::now();
const double lapse2a = std::chrono::duration_cast<std::chrono::microseconds>(end - begin).count();
std::cout << "Time difference = " << lapse2a << "[us]" << std::endl;
Example2 example2b_(3, 2); // Example2<double> till C++14
begin = std::chrono::steady_clock::now();
for (int i = 0 ; i < nout ; i++ )
std::cout << example2b_ << "\n";
end = std::chrono::steady_clock::now();
const double lapse2b = std::chrono::duration_cast<std::chrono::microseconds>(end - begin).count();
std::cout << "Time difference = " << lapse2b << "[us]" << std::endl;
Example3 example3a_(3.4, 2.5); // Example3<double> till C++14
begin = std::chrono::steady_clock::now();
for (int i = 0 ; i < nout ; i++ )
std::cout << example3a_ << "\n";
end = std::chrono::steady_clock::now();
const double lapse3a = std::chrono::duration_cast<std::chrono::microseconds>(end - begin).count();
std::cout << "Time difference = " << lapse3a << "[us]" << std::endl;
std::cout << "Time difference lapse1 = " << lapse1 << "[us]" << std::endl;
std::cout << "Time difference lapse2a = " << lapse2a << "[us]" << std::endl;
std::cout << "Time difference lapse2b = " << lapse2b << "[us]" << std::endl;
std::cout << "Time difference lapse3a = " << lapse3a << "[us]" << std::endl;
return 0;
}
It's the obvious way to implement it. It's also probably the most efficient. Use it.
The way you demonstrated in the question is the most basic way, which is also found in various C++ books. Personally I may not prefer in my production code, mainly because:
Have to write the boilerplate code for friend operator<< for each and every class.
When adding new class members, you may have to update the methods as well individually.
I would recommend following way since C++14:
Library
// Add `is_iterable` trait as defined in https://stackoverflow.com/a/53967057/514235
template<typename Derived>
struct ostream
{
static std::function<std::ostream&(std::ostream&, const Derived&)> s_fOstream;
static auto& Output (std::ostream& os, const char value[]) { return os << value; }
static auto& Output (std::ostream& os, const std::string& value) { return os << value; }
template<typename T>
static
std::enable_if_t<is_iterable<T>::value, std::ostream&>
Output (std::ostream& os, const T& collection)
{
os << "{";
for(const auto& value : collection)
os << value << ", ";
return os << "}";
}
template<typename T>
static
std::enable_if_t<not is_iterable<T>::value, std::ostream&>
Output (std::ostream& os, const T& value) { return os << value; }
template<typename T, typename... Args>
static
void Attach (const T& separator, const char names[], const Args&... args)
{
static auto ExecuteOnlyOneTime = s_fOstream =
[&separator, names, args...] (std::ostream& os, const Derived& derived) -> std::ostream&
{
os << "(" << names << ") =" << separator << "(" << separator;
int unused[] = { (Output(os, (derived.*args)) << separator, 0) ... }; (void) unused;
return os << ")";
};
}
friend std::ostream& operator<< (std::ostream& os, const Derived& derived)
{
return s_fOstream(os, derived);
}
};
template<typename Derived>
std::function<std::ostream&(std::ostream&, const Derived&)> ostream<Derived>::s_fOstream;
Usage
Inherit the above class for those classes for whom you want the operator<< facility. Automatically friend will get included into those class's definition via base ostream. So no extra work. e.g.
class MyClass : public ostream<MyClass> {...};
Preferably in their constructors, you may Attach() the member variables which are to be printed. e.g.
// Use better displaying with `NAMED` macro
// Note that, content of `Attach()` will effectively execute only once per class
MyClass () { MyClass::Attach("\n----\n", &MyClass::x, &MyClass::y); }
Example
From what you shared,
#include"Util_ostream.hpp"
template<typename T>
class Example : public ostream<Example<T>> // .... change 1
{
public:
Example(const T &_first_ele, const T &_second_ele) : first_(_first_ele), second_(_second_ele)
{
Example::Attach(" ", &Example::first_, &Example::second_); // .... change 2
}
private:
T first_;
T second_;
};
Demo
This approach has a pointer access per every print of the variable instead of direct. This negligible indirection should never be a bottle-neck in a code from the performance perspective.
Demo is slight more complex for practical purpose.
Requirements
The intention here is to improve readability and uniformity of printing the variables
Every printable class should have their separate ostream<T> regardless of inheritance
An object should have operator<< defined or ostream<T> inherited to be able to compile
Facilities
This is now shaping up as a good library component. Below are add-on facilities, I have added so far.
Using ATTACH() macro, we can also print variable in certain way; Variable printing can always be customised as per need by modifying the library code
If the base class is printable, then we can simply pass a typecasted this; Rest will be taken care
Containers with std::begin/end compatibility are now supported, which includes vector as well as map
The code shown in the beginning is shorter for the quick understanding purpose. Those who are further interested may click on the demo link above.

Error with << operator overload returning a std::string

I'm having troubles understanding the reason why the compiler accuses error, when the return type of a << operator overload is std::string. Could you please help me understand?
Bellow is an reproducible example, which gives a gigantic error.
class XY
{
int X__;
int Y__;
public:
XY(int x, int y):X__(x), Y__(y){}
~XY(){}
std::string operator<<(const XY_cartesiano& c)
{
std::stringstream ss;
ss << "{ " << X__ << ", " << Y__ << " }";
return ss.str();
}
int x() const{return X__;}
int y() const{return Y__;}
};
void main()
{
XY a(1,2);
std::cout << a;
}
Let's take something like this as an example:
cout << "My number is " << 137 << " and I like it a lot." << endl;
This gets parsed as
((((cout << "My number is ") << 137) << " and I like it a lot.") << endl);
In particular, notice that the expression cout << "My number is " has to evaluate to something so that when we then try inserting 137 with << 137 the meaning is "take 137 and send it to cout."
Imagine if cout << "My number is " were to return a string. In that case, the << 137 bit would try to use the << operator between a string on the left-hand side and an int on the right-hand side, which isn't well-defined in C++.
The convention is to have the stream insertion operator operator << return a reference to whatever the left-hand side stream is so that these operations chain well. That way, the thing on the left-hand side of << 137 ends up being cout itself, so the above code ends up essentially being a series of chained calls to insert things into cout. The signature of these functions therefore usually look like this:
ostream& operator<< (ostream& out, const ObjectType& myObject) {
// ... do something to insert myObject into out ... //
return out;
}
Now, everything chains properly. Notice that this function is a free function, not a member function, and that the left-hand side is of type ostream and the right-hand side has the type of your class in it. This is the conventional way to do this, since if you try overloading operator << as a member function, the left-hand side will be an operand of your class type, which is backwards from how stream insertion is supposed to work. If you need to specifically access private fields of your class in the course of implementing this function, make it a friend:
class XY {
public:
...
friend ostream& operator<< (ostream& out, const XY& myXY);
};
ostream& operator<< (ostream& out, const XY &myXY) {
...
return out;
}
Correct way to overload << operator in your case is
ostream& operator<<(ostream& os, const XY& c)
{
os << c.X__ <<" "<< c.Y__ ;
return os;
}
You have overloaded operator<< in a way that's incompatible with the conventions you must follow when you intend to use the operator with a std::ostream object like std::cout.
In fact, your operator<<'s signature has nothing to do with streams at all! It is just a member function of XY which takes another XY (which it then does not use), returns a string and has an unsual name. Here's how you would theoretically call it:
XY a(1,2);
XY b(1,2);
std::string x = (a << b);
The correct way to overload operator<< for use with streams is to make the operator a non-member function, add a stream reference parameter and return a stream reference to the stream argument. You also do not need a string stream; you write directly to the stream you get:
#include <iostream>
class XY
{
int x;
int y;
public:
XY(int x, int y) : x(x), y(y) {}
int X() const { return x; }
int Y() const { return y; }
};
std::ostream& operator<<(std::ostream& os, XY const& c)
{
os << "{ " << c.X() << ", " << c.Y() << " }";
return os;
}
int main()
{
XY a(1,2);
std::cout << a;
}

Ostream << operator overloading and it's return type

I learnt how to do operator overloading of Stream Insertion Operator. But one doubt remains.
#include<iostream>
class INT
{
int i;
friend std::ostream& operator<<(std::ostream&,INT&);
public:
INT():i(100){}
};
std::ostream& operator<<(std::ostream& obj,INT & data)
{
obj<<data.i;
return obj;
}
int main()
{
INT obj;
std::cout<<obj;
}
What significance return obj; has?
Do that return have any use further?
Are We forced to do that return because of the syntax of the operator<< without any usefulness?
Remember how you can write code like this:
cout << "The data is: " << somedata << endl;
This is actually the same as:
((cout << "The data is: ") << somedata) << endl;
For this to work, the << operator has to return the stream.