C++ operator overloading << with vector - c++

Hey guys I am new to C++ and I have a problem with this operator: (Also new in stackoverflow)
This is my class TestList:
class TestList{
public:
TestList() : listItems(10), position(0){};
TestList(int k) : listItems(k), position(0){};
int listItems;
int position;
std::vector<int> arr;
};
//my current operator is: What should be changed?
ostream& operator <<(ostream&, const TestList& tlist, int input){
os << tlist.arr.push_back(input);
return os;
}
//
int main() {
testList testlist(5);
testlist << 1 << 2 << 3; //how should I overload the operator to add these number to testlist.arr ?
return 0;
}
I hope someone could help me or can give me any tips? :)

The other answers are absolutely correct, I just want to say something general on operator<<. It always has the signature T operator<<(U, V), since it is always a binary operator, so it has to have exactly two arguments. Since the chain
a << b << c;
is evaluated as
(a << b) << c;
// That calls
operator<<(operator<<(a, b), c);
the types T and U should normally be the same, or at least compatible.
Furthermore, it is possible but very weird to assign the result of operator<< to something (like result = (a << b))). A good rule of thumb is "My code should not be weird". Therefore the type T should mostly be a reference (so X&) since otherwise it would only be a temporary copy that is unused. And that is pretty useless most of the time.
So in 90% of all cases, your operator<< should have the signature
T& operator<<(T&, V);

I think you mean the following
TestList & operator <<( TestList &tlist , int input )
{
tlist.arr.push_back( input );
return tlist;
}
Here is a demonstrative program
#include <iostream>
#include <vector>
class TestList{
public:
TestList() : listItems(10), position(0){};
TestList(int k) : listItems(k), position(0){};
int listItems;
int position;
std::vector<int> arr;
};
TestList & operator <<( TestList &tlist , int input )
{
tlist.arr.push_back( input );
return tlist;
}
std::ostream & operator <<( std::ostream &os, const TestList &tlist )
{
for ( const auto &item : tlist.arr )
{
std::cout << item << ' ';
}
return os;
}
int main()
{
TestList testlist(5);
testlist << 1 << 2 << 3;
std::cout << testlist << '\n';
return 0;
}
The program output is
1 2 3
You can even write instead of these two statements
testlist << 1 << 2 << 3;
std::cout << testlist << '\n';
only one statement
std::cout << ( testlist << 1 << 2 << 3 ) << '\n';
Pay attention to that there is a typo in your declaration
testList testlist(5);
There should be
TestList testlist(5);

Related

C++ copy c'tor does now take action. not clear why [duplicate]

This question already has answers here:
What's the difference between assignment operator and copy constructor?
(8 answers)
Closed 4 years ago.
I have this code:
the output of the code is:
cons intcons op+ intcons ;
copycons op+ intcons op+= ;
get_val 3
class declaration::
#include<iostream>
using namespace std;
class Int {
public:
// constructors
Int() : val_(0) { cout << "cons "; }
Int(int n) { val_ = n; cout << "intcons "; }
Int(const Int &v) : val_(v.val_) { cout << "copycons "; }
Int(Int &&v_) { val_ = v_.val_; cout << "mov ctor " ; };
// operations
int get_val() {
cout << "get_val "; return val_;
}
Int operator+(const Int &v) {
cout << "op+ ";
return Int(val_ + v.val_);
}
Int & operator=(const Int &v) {
cout << "op= ";
if (this != &v) {
val_ = v.val_;
}
return *this;
}
Int & operator+=(const Int &v) {
cout << "op+= ";
val_ += v.val_;
return *this;
}
private:
int val_; // value stored in this Int
};
and this is main:
int main(){
Int zero;
Int one = zero + 1;
cout << ";\n";
Int two = zero;
two += one + one;
cout << ";\n";
cout << two.get_val() + 1; cout << endl;
return 0;
}
I was looking at the codes output, and I could agree with each operation that happens and with every output. but one thing isn't clear to me at all. I wonder, why in the first line of the output there isn't use with the copy c'tor?
at first I though maybe it is a move c'tor.
then I built one and it doesn't seemed like the compiler was using it.
can anyone please tell me what is going on? thank you!
I think you are confusing the assignment operator with the copy constructor.
Int two = zero; will cause the copy constructor to be called.
two = zero or two = 1 will cause the assignment operator to be called.
https://techdifferences.com/difference-between-copy-constructor-and-assignment-operator.html

pretty printing nested vectors

I have the following code to pretty-print generic vectors -:
// print a vector
template<typename T1>
std::ostream& operator <<( std::ostream& out, const std::vector<T1>& object )
{
out << "[";
if ( !object.empty() )
{
std::copy( object.begin(), --object.end(), std::ostream_iterator<T1>( out, ", " ) );
out << *--object.end(); // print the last element separately to avoid the extra characters following it.
}
out << "]";
return out;
}
I am getting a compiler error if I try to print a nested vector from it.
int main()
{
vector<vector<int> > a;
vector<int> b;
// cout << b ; // Works fine for this
cout << a; // Compiler error
}
I am using GCC 4.9.2 with the -std=c++14 flag.
The error message given by the compiler is -:
no match for 'operator<<' (operand types are
'std::ostream_iterator<std::vector<int>, char, std::char_traits<char>::ostream_type {aka std::basic_ostream<char>}' and 'const std::vector<int>')
std::copy( object.begin(), --object.end(), std::ostream_iterator<T1>( out, ", " ) );
You are using copy to ostream iterator which is not defined for vector of std::vector<>. One work around is to implement operator << in terms of operator << of children.
if ( !object.empty() )
{
//std::copy( object.begin(), --object.end(), std::ostream_iterator<T1>( out, ", " ) );
for(typename std::vector<T1>::const_iterator t = object.begin(); t != object.end() - 1; ++t) {
out << *t << ", ";
}
out << *--object.end(); // print the last element separately to avoid the extra characters following it.
}
Live example here
This method will not work for the same reason for std::vector<my_type> if opeartor << is not defined for class my_type
Just using a normal forloop instead of std::copy would solve this issue. As #Mohit suggested, the ostream iterator is not defined for nested vectors.
#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>
#include <functional>
using namespace std;
// print a vector
template<typename T1>
std::ostream& operator <<( std::ostream& out, const std::vector<T1>& object )
{
out << "[";
if ( !object.empty() )
{
for(typename std::vector<T1>::const_iterator
iter = object.begin();
iter != --object.end();
++iter) {
out << *iter << ", ";
}
out << *--object.end();
}
out << "]";
return out;
}
int main() {
std::vector<std::vector<int> > a;
std::vector<int> b;
b.push_back(1);
b.push_back(2);
std::vector<int> c;
c.push_back(3);
c.push_back(4);
std::cout << b << std::endl;
std::cout << c << std::endl;
a.push_back(b);
a.push_back(c);
cout << a; // Compiler error
return 0;
}
Output would look like this:
[1, 2]
[3, 4]
[[1, 2], [3, 4]]

Print different values with different types depending on some condition with operator<<?

Let's say I want to print the number args if they are > 1 or "none" if they are <= 1. The only way I know how to do this is:
cout << "number of args: ";
if (argc > 1)
cout << argc - 1;
else
cout << "none";
cout << endl;
But then I can't chain the << operator. Ideally, I would like to be able to do something like:
cout << "number of args: "
<< argc > 1 ? argc - 1 : "none"
<< endl;
But this isn't possible because the types from a ternary if are different.
Ideas?
The simple way. Handle with a string.
std::cout << "number of args: "
<< (argc > 1 ? std::to_string(argc - 1) : "none")
<< std::endl;
It has some superfluous cost to change the string. But it is easy to read and maintain if it is used once. And the reason the parentheses are required is that the shift operator(<<) has higher precedence than ternary conditional operator(?:) or relational operators (>).
You can make your own class to do the limit printing:
class limit {
int lim;
int k;
public:
limit(int lim_, int k_) : lim(lim_), k(k_) {}
friend ostream& operator<<(ostream& ostr, const limit& lim);
};
ostream& operator<<(ostream& ostr, const limit& lim) {
if (lim.k < lim.lim) {
ostr << "none";
} else {
ostr << lim.k - lim.lim;
}
return ostr;
}
int main() {
cout << "Hello " << limit(1, 15) << endl;
cout << "World " << limit(1, -1) << endl;
return 0;
}
Demo.
The limit class holds two numbers - the limit (1 in the demo) and the number to be printed. It provides an operator << for printing, which uses your conditional statement to print either the value over the limit, or "none". This lets you write cout << limit(1, argc), and produce the desired printout.
If you place the << within the ternary expressions, it unifies the types for both the true and false cases.
argc > 1 ? std::cout << argc - 1 : std::cout << "none";
You can use a helper template function to make things a bit more seamless:
template <typename T>
std::ostream & argp (const T &x) {
return std::cout << "number of args: " << x;
}
(argc > 1 ? argp(argc - 1) : argp("none")) << std::endl;
If you want a more general solution, you could create a (template) class that stores references to two objects and a bool. Then overload operator<< to choose which member to print based on the bool.
template<typename T, typename U>
class be_careful_this_class_holds_references_to_its_constructor_arguments
{
public:
be_careful_this_class_holds_references_to_its_constructor_arguments(
bool b, T const& t, U const& u)
:choose_first(b), first(t), second(u)
{}
friend std::ostream& operator<<(
std::ostream& os,
be_careful_this_class_holds_references_to_its_constructor_arguments const& p)
{
if (p.choose_first)
os << p.first;
else
os << p.second;
return os;
}
private:
bool choose_first;
T const& first;
U const& second;
};
Using this class is a bit cumbersome though, you have to name the types. You can fix that with a helper function:
template<typename T, typename U>
be_careful_this_class_holds_references_to_its_constructor_arguments<T,U>
pick(bool choice, T const& first, U const& second)
{
return be_careful_this_class_holds_references_to_its_constructor_arguments<T,U>(choice,first,second);
}
Then you can just call this function, passing a condition to the first parameter, and your two options of what to print to the second and third parameters:
std::cout << pick(argc > 1, argc - 1, "none") << std::endl;
Just for the sake of adding to the existing craziness....
Eventual usage supported:
xstream xs(std::cout) << If(argc <= 1) << argc - 1 << _else << "none" << _endif << '\n';
Note that this does not short-circuit evaluation of the "if" or "else" branches the way ?, : and ; does, but it doesn't require a conversion to a common type either....
Implementation (also at ideone.com.
#include <iostream>
using namespace std;
struct If { If(bool active) : active_(active) { } bool active_; };
struct Else { } _else;
struct Endif { } _endif;
class xstream
{
public:
xstream(std::ostream& os) : os_(os) { }
template <typename T>
friend xstream& operator<<(xstream& s, const T& t)
{
if (s.active_) s.os_ << t;
return s;
}
private:
bool active_;
std::ostream& os_;
};
template <>
xstream& operator<< <If>(xstream& s, const If& _if)
{
s.active_ = _if.active_;
return s;
}
template <>
xstream& operator<<<Else>(xstream& s, const Else& _else)
{
s.active_ ^= true;
return s;
}
template <>
xstream& operator<<<Endif>(xstream& s, const Endif& _endif)
{
s.active_ = true;
return s;
}
int main(int argc, const char* argv[])
{
xstream xs(std::cout);
xs << If(argc <= 1) << argc - 1 << _else << "none" << _endif << '\n';
}
(Note that the xstream constructor only keeps a reference to the stream it's controlling, so the latter's lifetime must outlive the former's use under penalty of undefined behaviour).

Error : No operator “<<” matches these operands

I'm still fairly rusty at c++ and I'm having trouble understanding my issue. The error message that I am receiving is "No operator '<<' matches these operands" The code I have:
for(int i = 0; i < ruleList.size(); i++)
{
cout << ruleList[i].lhs << endl;
cout << ruleList[i].rhs << endl; // Problem printing this
}
struct Rules
{
string lhs;
vector<string> rhs;
}rule;
vector<Rules> ruleList;
Would this be the appropriate way to do this? I did the lhs the same way and it works fine.
rule.rhs.push_back(token);
ruleList.push_back(rule);
There is no operator<< defined for standard containers. You will need to write a print function, something along the lines of:
void print(std::ostream& out, std::vector<std::string> const & data) {
std::copy(data.begin(), data.end(),
std::ostream_iterator<std::string>(out, " "));
}
And then use it as:
print(std::cout, ruleList[i].rhs);
std::vector does not define an operator <<. You can use a std::ostream_iterator to format a list:
std::copy( ruleList[i].rhs.begin(), ruleList[i].rhs.end(),
std::ostream_iterator< std::string >( std::cout, ", " ) );
This is a bit imperfect in that ", " is printed after the final element, but that can be worked around.
You need to write your own << operator for struct rules. It should look something like this in C++11:
struct rules {
string lhs;
std::vector<std::string> rhs;
// apparently it's a good idea to keep this out of std:: namespace
inline static std::ostream & operator << (std::ostream & out, const rules & r) {
out << r.lhs << std::endl;
//for (int i = 0; i < v.length(); i++)
for (auto & s : r.rhs) {
out << s;
}
out << std::endl;
return out;
}
}
MSDN has a write up here: http://msdn.microsoft.com/en-us/library/1z2f6c2k.aspx

No operator << matches these operands [duplicate]

This question already has answers here:
How can I use cout << myclass
(5 answers)
Closed 4 months ago.
I've been reading questions here for an hour or two regarding this error I'm getting and most of them forgot to #include string (which I had already done), or to overload the << operator.
Here's the code in question:
void Student::getCoursesEnrolled(const vector<Course>& c)
{
for (int i = 0; i < c.size(); i++)
{
cout << c[i] << endl;
}
}
And the error I'm getting:
Error: No operator matches these operands
operand types are: std::ostream << const Course
All I'm trying to do is return the vector. I read about overloading the << operator but we haven't learned any of that in class so I'm assuming there is another way of doing it?
I appreciate your time!
All I'm trying to do is return the vector.
Not quite; you're trying to print it using cout. And cout has no idea how to print a Course object, unless you provide an overloaded operator<< to tell it how to do so:
std::ostream& operator<<(std::ostream& out, const Course& course)
{
out << course.getName(); // for example
return out;
}
See the operator overloading bible here on StackOverflow for more information.
The problem is that operator << is not overload for type Course objects of which you are trying to output in statement
cout << c[i] << endl;
You need to overload this operator or write your own function that will output an object of type Course in std::ostream
For example let assume that below is a definition of class Course
class Course
{
private:
std::string name;
unsigned int duration;
public:
Course() : duration( 0 ) {}
Course( const std::string &s, unsigned int n ) : name( s ), duration( n ) {}
std::ostream & out( std::ostream &os ) const
{
return ( os << "Course name = " << name << ", course duration = " << duration );
}
};
When you can write
std::vector<Course> v = { { "A", 1 }, { "B", 2 }, { "C", 3 } };
for ( const Course &c : v ) c.out( std::cout ) << std::endl;
Instead member function out you can overload operator <<. For example
class Course
{
private:
std::string name;
unsigned int duration;
public:
Course() : duration( 0 ) {}
Course( const std::string &s, unsigned int n ) : name( s ), duration( n ) {}
friend std::ostream & operator <<( std::ostream &os, const Course & c )
{
return ( os << "Course name = " << c.name << ", course duration = " << c.duration );
}
};
and use it as
std::vector<Course> v = { { "A", 1 }, { "B", 2 }, { "C", 3 } };
for ( const Course &c : v ) std::cout << c << std::endl;
The stream operator << is used to "output" some representation of that object. If you don't want to overload the operator yet just pick some property to output instead:
for (int i = 0; i < c.size(); i++)
{
cout << c[i].Name << endl; // assuming Name is a property of Course
}
When you DO overload the operator you just decide then what the proper representation of a Course is:
ostream& operator<< (ostream &out, Course &c)
{
out << c.Name "(" << c.Description << ")";
return out;
}
Your Course class needs to implement an operator:
class Course
{
public:
/*
* Your code here
*/
// Probably missing this:
friend std::ostream& operator << (std::ostream& os, const Course& course)
{
os << course.name(); // etc..
return os;
};
}; // eo class Course
Since you haven't yet learned to overload operator<<, what you can do instead is to print each member of your Course class. You haven't posted the definition of Course, but perhaps it's something like this:
class Course
{
public:
int get_number() { return _number; }
const std::string& get_name() { return _name; }
private:
int _number;
std::string _name;
};
then you can say:
void Student::getCoursesEnrolled(const vector<Course>& c)
{
for (int i = 0; i < c.size(); i++)
{
cout << c[i].get_number() << " "
<< c[i].get_name() << std::endl;
}
}
Your problem is this particular part:
cout << c[i]
In your case c[i] is an object of type Course as dvnrrs correctly pointed out. So either:
implement the overloaded << operator for your object OR
if your Course object is in someway a typedef to a primitive try explicitly casting it to a string type (or similar)