I have a vector of pointers, and I'm trying to overload the ostream operator to make printing easier. However, I can't seem to get the function to be called. Here is my code:
std::vector<Set*> sets;
for (int i = 0; i < sets.size(); i++) {
std::cout << sets[i] << std::endl;
}
std::ostream& operator<<(std::ostream& out, const Set* s) {
//Print set code
}
I loop through all the sets and call the specific set for printing by putting sets[i] in the ostream, yet the function is not called. It just prints the address of sets[i]. I had this working when I had a vector of Set, but when I tried to change it to a vector of Set*, I couldn't get it to work. Where am I going wrong?
Overload resolution is done using the declarations visible to the compiler at the point of call. You'll need to move your operator<< overload, or at least a declaration of it, above the code using it.
And behold, it works: http://ideone.com/1BeACP
Related
I'm new to this website and a bit new in programming. I'm using vector for the first time and I want to print content of it but I'm getting addresses instead of normal words. I don't know how to do that in other way than this.
My vector:
vector<Component*> vect;
and my code for printing:
void Frame::print() {
for (int i = 0; i < vect.size(); i++)
cout << vect[i] << endl;
}
You are storing pointers in your vector. The value of a pointer is a memory address, therefore you are seeing addresses in your output. You need to dereference the pointers to access the actual Component objects:
void Frame::print()
{
for (int i = 0; i < vect.size(); i++)
{
Component *component = vect[i];
cout << *component << endl; // <-- not the extra '*'
}
}
In order for this to work, an operator<< overload for Component is also required:
ostream& operator<<(ostream &out, const Component &comp)
{
// print comp values to out as needed...
return out;
}
Recommended reading:
Operator overloading
You also need to study up on pointers and references in general.
vect is a vector (aka a lump of contiguous storage) of Component * (aka Component pointers) that is it's a chunk of memory with addresses of other chunks of memory which the compiler will treat as a Component class object. Printing those addresses via cout will just give you a big list of meaningless numbers.
What I suspect you want to do is probably not store a vector of Component pointers at all and just store a vector of Components. It's frowned upon in C++ these days to store raw pointers unless you know exactly what you are doing. If you really do want pointers you should use a vector of std::unique_ptr and std::make_unique.
Once you start trying to print Components rather than addresses of them you will most likely see that there is no << operator for Component. You will need to write one. Something like
std::ostream& operator<<(std::ostream &stream, const Component&component)
{
stream << component.string_member;
return stream;
}
Problem: overload the default << operator for a vector<int> v variable, so that cout << v will print each element sequentially. Here I saw one option as proposed by Jason Iverson in the previous question
template<typename T>
std::ostream& operator<<(std::ostream& s, std::vector<T> t) {
s << "[";
for (std::size_t i = 0; i < t.size(); i++) {
s << t[i] << (i == t.size() - 1 ? "" : ",");
}
return s << "]" << std::endl;
}
Obviously this should work for any type of elements, however since I am only concerned with int, I simplified the function as
ostream& operator << (ostream &os, const vector<int> &v){
for (auto x: v){
os << " " << x;
}
return os;
}
It just works fine.
So my question is
As far as vector<int> v is concerned, what is the caveat of not using template?
Apart from being general-purpose, what is the advantage of Jason's solution?
Thanks!
Deeper thoughts:
The above question was poorly phrased, and thanks to the comments, I believe it makes sense to rephrase it.
Question: in C++, what is the cost of using template where a single-type function is enough?
Credits to #Marco A and #Walter, this question could be closed.
One of the main points of C++ is generic programming and templates are the way to do this.
The advantage is pretty obvious: you don't have to write the same/similar piece of code more than once and you don't have to debug/maintain similar pieces of code, but just one. (All of this falls in your category "general purpose", so there is no advantage beyond that).
There is actually some disadvantage, because a template is not a function (or class). A function (or class) will only be created from the template at compile time when it is actually used, whereas your (non-template) function may be pre-compiled. This has two implications: (1) more compiling and (2) that certain syntax errors in the code only turn up when the template is used with arguments for which they won't work. The template in your post, for example, won't compile if ostream << T has not been defined.
So I found this code on here that I'm working with:
#include <iostream>
#include <cstdlib>
#include <vector>
using namespace std;
struct Something{
int x;
int y;
};
int main()
{
vector <Something> v;
int x, y;
cin >> x >> y;
Something temp;
temp.x = x;
temp.y = y;
v.push_back(temp);
for (size_t i = 0; i < v.size(); i++)
{
cout << v[i] << endl; // Error: No operator "<<" matches these operands. Operand types are std::ostream << Something
}
}
Basically, I'm trying to get multiple ints into one vector index.
cout is not working when I try to print the contents of the vector.
First of all, am I even doing this multiple int thing right? I'm relatively new to C++.
And if I am doing this right, any ideas as to why cout isn't working?
I also tried v.push_back({x,y}) and that didn't work. Any idea what is going on with cout? Thanks a lot.
EDIT:
Thank you very much so far. I just have one more question. If I were to modify my code to take multiple inputs and later wanted everything in the vector sorted according to "y" from largest to smallest.
Example (Original Vector Contents (x,y))
12 4
1 2
4 10
1 1
1 2
Sorted according to 'y' (largest to smallest)
4 10
12 4
1 2
1 2
1 1
I know how to do a regular sort but not one according to the second number (y). How do I do that? Thanks a lot.
Just like the error says, there's no overloaded operator<< function declared for your structure.
There are three possible solutions: The first is to output each member of the structure, like
std::cout << v[i].x << ' ' << v[i].y << '\n';
The other is to create a function that does the above, either as a member function or as a non-member function.
The third solution is to create an overloaded operator<< function for the structure:
std::ostream& operator<<(std::ostream& os, Something const& something)
{
return os << something.x << ' ' something.y;
}
I recommend you find a good beginners book on C++ and read the chapters about output, structures and classes, and operators and operator overloading.
cout does not work for your struct because it was not defined to do so.
I think you can find the answer here.
Overloading operators in typedef structs (c++)
operator<< is not automatically available between cout and objects of user defined classes. They need to be defined before you can be used.
In your case, you need to define a friend function inside the struct definition's body
friend std::ostream& operator<<(std::ostream& out, Something const& s);
to be able to use
cout << v[i] << endl;
The implementation of the function is not too difficult.
std::ostream& operator<<(std::ostream& out, Something const& s)
{
return out << s.x << " " << s.y;
}
If you want be able to use:
Something s;
std::cin >> s;
you'll have to define a similar function.
The problem is that << is an operator. It is defined on std::cout (which is an std::ostream) for a number of types. For example, it's defined for int, which is why this works:
std::cout << 3;
However, you are trying to apply the operator<< to your own Something class, but it has no such operator definition. You can add it like this:
struct Something {
// Other stuff here
friend std::ostream& operator<<(std::ostream& os, Something const& smth) ;
};
std::ostream& operator<<(std::ostream& os, Something const& smth) {
os << "(" << smth.x << ", " << smth.y << ")";
return os;
}
Then your code should work. Overloading this operator is actually more difficult than overloading others because you need to understand what friend does.
Edit:
friend is actually not needed in your case, because x and y are public. But in the general case you need it to be able to print private members of your class.
Edit 2:
To make the previous edit clear, you can omit the entire in-struct declaration of the operator, since it will be looked up globally. You only need it (and then it needs to be friendly) if the operator needs to read private members.
here is the problem:
In my first class i have a vector, a double variable and I overload the comparison operators. Here is the relevant code:
class City
{
double distance;
std::vector<int> coordinates;
bool operator<(const City& city) const
{
return this->distance < city.distance;
}
// same for the greater-than operator but changing "<" to ">"
};
In another class I have a vector of cities, which I have to sort every time a condition is met. For that I have a struct defined as follows:
EDIT: (reference instead of value)
struct CitySortHelper {
bool operator() (const City &x, const City &y) const { return x < y; }
} city_sort;
Now the problem part, when I sort the vector new City objects appear, and I can't explain why:
EDIT:
// this prints all current objects in the vector
for (int i = 0; i < totalCities; i++) {
std::cout << cities->at(i) << std::endl;
}
// after the following line I get new City objects in the
// vector, that weren't there before the sort. The new objects
// always have distance = 0 and random values in the coordinates
std::sort(cities->begin(), cities->end(), city_sort);
// using the sort with no predicate also gives the same faulty results
std::sort(cities->begin(), cities->end());
EDIT: (the copy constructor and assignment operator)
City(const City &city)
{
this->distance = city.distance;
this->coordinates = city.coordinates;
}
City& operator= (const City &city)
{
this->distance = city.distance;
this->coordinates = city.coordinates;
return *this;
}
The weird part is that this only happens if I sort the City objects in ascending order, i.e. if I change the comparator operator in the CitySortHelper from "<" to ">" everything works fine.
Any ideas why this happens ?? Any help is appreciated.
CitySortHelper needs to take parameters by const reference, not by value. Another thing to keep in mind is that sort uses assignment operator for the City; check that your assignment operator is working correctly. Taking care of these two issues should fix the problem.
Change your sort helper to have
bool operator() ( const City& x , const City& y) const
And also check that City copy constructor and assignment operator do the proper thing
You shouldn't use std::sort() if you want to preserve order, you should use std::stable_sort(). stable_sort guarantees elements maintain their relative order, sort doesn't.
Also, it doesn't seem like sort is your problem here. It seems there are City objects getting pushed into the vector somewhere, and you aren't noticing them because you're checking on a variable for size instead of the vector's iterators. Try printing like this instead and tell us what comes out:
for (std::vector <City> ::iterator it = cities->begin(); it != cities->end(); ++it) {
std::cout << *it << std::endl;
}
I think I've declared a Vector with an object correctly. But, I don't know how to access it's members when looping with Iterator.
In my code, the line --->> cout << " " << *Iter;
How do I print the contents of the members? Like *Iter.m_PackLine ???
Not sure if I used the correct terminology, but appreciate the help! Thanks
class CFileInfo
{
public:
std::string m_PackLine;
std::string m_FileDateTime;
int m_NumDownloads;
};
void main()
{
CFileInfo packInfo;
vector<CFileInfo, CFileInfo&> unsortedFiles;
vector<CFileInfo, CFileInfo&>::iterator Iter;
packInfo.m_PackLine = "Sample Line 1";
packInfo.m_FileDateTime = "06/22/2008 04:34";
packInfo.m_NumDownloads = 0;
unsortedFiles.push_back(packInfo);
packInfo.m_PackLine = "Sample Line 2";
packInfo.m_FileDateTime = "12/05/2007 14:54";
packInfo.m_NumDownloads = 1;
unsortedFiles.push_back(packInfo);
for (Iter = unsortedFiles.begin(); Iter != unsortedFiles.end(); Iter++ )
{
cout << " " << *Iter; // !!! THIS IS WHERE I GET STUMPED
// How do I output values of the object members?
}
} // end main
cout << " " << *Iter;
will only work if CFileInfo has an overloaded operator<< that can output your struct. You can output individual members of the struct instead like this:
cout << " " << Iter->m_PackLine;
Alternatively, the following is equivalent to that:
cout << " " << (*Iter).m_PackLine;
You have to put parentheses around *Iter, since the member-access operator binds thighter otherwise.
On a side-node, make your main function return int instead of void. making it return void is not valid in C++.
You declare the vector like this:
vector<CFileInfo, CFileInfo&> unsortedFiles;
The second argument to vector should be another thing. It's not needed for your code to give the vector a second argument at all. Just use this:
vector<CFileInfo> unsortedFiles;
Another thing i noticed is you increment the iterator using Iter++ (called postfix increment). For iterators, always prefer ++Iter, which is called prefix increment.
Use (*iter).member or iter->member.
You can also use temporaries:
CFileInfo &fileInfo = *iter;
cout << " " << fileInfo.myMember;
Also, for what you're doing, you'd probably want a const_iterator instead of an (mutable) iterator.
In addition, std::vector is a template accepting a typename and an allocator, not two typenames. You can use the default allocator by stripping the second template argument:
vector<CFileInfo> unsortedFiles;
vector<CFileInfo>::iterator Iter;
Some nit-picking:
main should return an int.
It'd probably be best to declare your iterator variable in the for statement.
It'd probably be faster in run-time performance to use the prefix ++ operator (++iter) instead of the postfix operator (iter++) in your for loop.
No need for your comment about main() ending.
This is the first problem I noticed:
std::vector is a template.
You have:
vector unsortedFiles;
you need something like:
vector<CFileInfo> unsortedFiles;
Now that I think about it, your template definition may have just gotten parsed out by the stackoverflow comment system.
iter->m_PackLine
or
(*iter).m_PackLine
First correct you'r vector declaration:
vector<CFileInfo > unsortedFiles;
Next you need to define an output operator for your class:
std::ostream& operator<<(std::ostream& str,CFileInfo const& data)
{
// Do something here
/* Potentailly you could do this
* But this requires that this function be a friend of the class
str << data.m_PackLine << ":"
<< data.m_FileDateTime << ":"
<< data.m_NumDownloads << ":";
* Or you could do this
data.print(str); // Make print a public const method.
*/
return str;
}
Usually you either make the output operator a friend of your class or provide a public print method that takes a stream. Either way you can then access the members and stream them manually to the output.
Once you have the output iterator defined you can change your loop to use the standard library versions:
std::for_each(unsortedFiles.begin()
unsortedFiles.end()
std::ostream_iterator<CFileInfo>(std::cout," ")
);
Thanks all, wish I could grant multiple points for the answers :)
litb also pointed out a problem I was having in my declaration of the vector. I removed the second argument in the vector declaration and it worked.
Stackoverflow parsed out some of my code, I'll be more careful in posting next time.
vector<CFileInfo, CFileInfo&> will not work at all. The second parameter to vector is the allocator the vector uses, and CFileInfo does not meet those requirements, nor does any reference type. I think you just want vector<CFileInfo>, the iterators and members will return CFileInfo& automatically.