Adding multiple ints to one vector index? 'Cout' not working - c++

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.

Related

How to overload >> operator to take a comma separated variable argument list

--Quick Before
So before anyone says this question has been answered on another post it hasn't... It was a homework question in the other post and the original question was never answered only told they were wrong.
--Question
I am trying to overload the >> operator to be able to pass in n-number of variables seperated by commas into an object like so...
Mat M = (Mat_<double>(3,3) << 1, 0, 0, 0, 1, 0, 0, 0, 1);
I am trying to reuse their usage of the comma seperated argument list but I can't seem to get it to work.
When I overload the << operator like so
void operator<< (const double& is)
{
std::cout << "hiya " << is << std::endl;
}
and attempt to use it like so
mat << 1.0, 2.0;
only the first value is passed to the operator... The second value is never 'used' as I believe that << has a higher presidence than ,
So my question is what are they doing in libraries like eigen and openCV to be able to have this functionality. I have looked through their code to attempt to understand it but it appears to require a deeper understanding of how C++ works that I don't have and I was hoping someone here could shed some light on it.
Thanks in advance for any advice.
You'll have to overload the insertion operator (<<) and the comma operator (,) such that
mat << 1.0, 2.0;
is translated as:
mat.operator<<(1.0).operator,(2.0);
or
operator,(operator<<(mat, 1.0), 2.0);
Here's a demonstrative program that illustrates the idea without doing anything useful.
struct Foo
{
};
Foo& operator<<(Foo& f, double)
{
std::cout << "In operator<<(Foo& f, double)\n";
return f;
}
Foo& operator,(Foo& f, double)
{
std::cout << "In operator,(Foo& f, double)\n";
return f;
}
int main()
{
Foo f;
f << 10, 20, 30;
}
and its output
In operator<<(Foo& f, double)
In operator,(Foo& f, double)
In operator,(Foo& f, double)
You would have to create a temporary from the first argument and surround the entire comma list in parenthesis:
myObj >> (some_temporary(3), 1, ...);
which would require that some_temporary be either a type or helper-function-returning-object that overloads the comma operator and your >> would need to be able to take that type. Otherwise the precedence of >> would "win" and therefore be evaluated before the comma expression is seen.
An uglier alternative would be to have your >> return a type that overloads operator ,() but I believe the first is preferable (actually, I would say this entire scheme is un-preferable).

C++ overloading operator with/without defining a template

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.

Justification/Discussion why std::sort isn't forced to use std::swap

I recently wrote code (relevant SO answer, associated code) whose swap operation was intended to have different semantics than a combination of copy construction and copy assignment. That's where I recognized that std::sort doesn't always use std::swap or any swap function found through ADL.
For those who aren't familiar with this I put together a small example:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
namespace thing {
struct thing {
int dummy;
operator int (void) const {
return dummy;
}
thing (int value) : dummy (value) {}
thing (thing const & other) : dummy (other.dummy) {
cout << "copy " << this << " from " << &other << endl;
}
thing & operator=(thing const & other) {
dummy = other.dummy;
cout << "assign " << this << " from " << &other << endl;
}
void swap (thing & other) {
// not called
}
};
void swap (thing & lhs, thing & rhs) {
// not called
}
}
int main() {
vector<thing::thing> data = {1, 21, 42};
cout << "sorting now" << endl;
sort (begin (data), end (data), greater<int>{});
return 0;
}
Now the fact that std::sort isn't always using std::swap has been addressed multiple times here on SO:
std::sort does not always call std::swap
Does STL sort use swap or binary copy?
My question is: Has there been any consideration, in terms of a proposal or discussion, to force std::sort (and similar standard library functions) to actually use std::swap?
To me it feels a bit ... under specified ... that for the correct behavior of my code it's swap operation has to have the same semantics as the combination of copy (move) construction and copy (move) assignment.
I'm well aware of the fact that the actual implementation (using a copy followed by multiple assignments) is far more effective than applying swap to any two elements for sorting.
Definitely. See issue LWG 226 and paper N1523
A major issue is exactly what to call. ::std::swap cannot be overloaded, and unqualified swap may not be the right function. In fact, the finance industry has always been a major user of C++, and for them swap might very well be a swap.

C++ Overload operator << to work with vector of pointers

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

C++ STL Vector Iterator accessing members of an Object

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.