This question already has answers here:
no match for ‘operator<<’ in ‘std::operator
(6 answers)
Closed 5 years ago.
I am developing gsoap web service where I am retrieving vectors of objects in return of a query. I have two ways to do it: first by simple loop and by iterator. None of them working.
The error is:
error: no match for 'operator<<' in 'std::cout
mPer.MultiplePersons::info.std::vector<_Tp, _Alloc>::at<PersonInfo, std::allocator<PersonInfo> >(((std::vector<PersonInfo>::size_type)i))'
MultiplePersons mPer; // Multiple Person is a class, containing vector<PersonInfo> info
std::vector<PersonInfo>info; // PersonInfo is class having attributes Name, sex, etc.
std::vector<PersonInfo>::iterator it;
cout << "First Name: \t";
cin >> firstname;
if (p.idenGetFirstName(firstname, &mPer) == SOAP_OK) {
// for (int i = 0; i < mPer.info.size(); i++) {
// cout << mPer.info.at(i); //Error
//}
for (it = info.begin(); it != info.end(); ++it) {
cout << *it; // Error
}
} else p.soap_stream_fault(std::cerr);
}
It's obvious that operator overloading operator<< in cout is the problem. I have looked at several problems related to this, but no one helped me out. If someone can provide a concrete example on how to solve it, it would be very appreciated. (Please do not talk in general about it, I am new to C++ and I have spent three days on it searching for solution.)
You need to provide an output stream operator for PersonInfo. Something like this:
struct PersonInfo
{
int age;
std::string name;
};
#include <iostream>
std::ostream& operator<<(std::ostream& o, const PersonInfo& p)
{
return o << p.name << " " << p.age;
}
This operator allows expressions of the type A << B, where A is an std::ostream instance (of which std::cout is one) and B is a PersonInfo instance.
This allows you do do something like this:
#include <iostream>
#include <fstream>
int main()
{
PersonInfo p = ....;
std::cout << p << std::endl; // prints name and age to stdout
// std::ofstream is also an std::ostream,
// so we can write PersonInfos to a file
std::ofstream person_file("persons.txt");
person_file << p << std::endl;
}
which in turn allows you to print the de-referenced iterator.
The result of *it is an L-value of type PersonInfo. The compiler is complaining that there is no operator<< which takes a right-hand side argument of type PersonInfo.
For the code to work, you need to provide such an operator, for example like this:
std::ostream& operator<< (std::ostream &str, const PersonInfo &p)
{
str << "Name: " << p.name << "\nAge: " << p.age << '\n';
return str;
}
The exact implementation of the operator depends on your needs for representing the class in output, of course.
What it's telling you is that there isn't a known wway to cout (console output) the contents of *it.
it is an iterator - think of this like a pointer in a list
the list is info so *it is current item in the info, which is a list of PersonInfo items.
So cout << *it; says output to the console the PersonInfo that it is currently referencing.
But the error message is telling you that the compiler doens't know how PersonInfo should be rendered to the console.
What you need to do is create an operator called << that takes an object that cout is (ostream) and a PersonInfo object and then writes the various bits of the PersonInfo to cout.
Related
I am trying to overload
<<
operator. For instance
cout << a << " " << b << " "; // I am not allowed to change this line
is given I have to print it in format
<literal_valueof_a><"\n>
<literal_valueof_b><"\n">
<"\n">
I tried to overload << operator giving string as argument but it is not working. So I guess literal
" "
is not a string. If it is not then what is it. And how to overload it?
Kindly help;
Full code
//Begin Program
// Begin -> Non - Editable
#include <iostream>
#include <string>
using namespace std;
// End -> Non -Editable
//---------------------------------------------------------------------
// Begin -> Editable (I have written )
ostream& operator << (ostream& os, const string& str) {
string s = " ";
if(str == " ") {
os << '\n';
}
else {
for(int i = 0; i < str.length(); ++i)
os << str[i];
}
return os;
}
// End -> Editable
//--------------------------------------------------------------------------
// Begin -> No-Editable
int main() {
int a, b;
double s, t;
string mr, ms;
cin >> a >> b >> s >> t ;
cin >> mr >> ms ;
cout << a << " " << b << " " ;
cout << s << " " << t << " " ;
cout << mr << " " << ms ;
return 0;
}
// End -> Non-Editable
//End Program
Inputs and outputs
Input
30 20 5.6 2.3 hello world
Output
30
20
5.6
2.3
hello
world
" " is a string-literal of length one, and thus has type const char[2]. std::string is not related.
Theoretically, you could thus overload it as:
auto& operator<<(std::ostream& os, const char (&s)[2]) {
return os << (*s == ' ' && !s[1] ? +"\n" : +s);
}
While that trumps all the other overloads, now things get really hairy. The problem is that some_ostream << " " is likely not uncommon, even in templates, and now no longer resolves to calling the standard function. Those templates now have a different definition in the affected translation-units than in non-affected ones, thus violating the one-definition-rule.
What you should do, is not try to apply a global solution to a very local problem:
Preferably, modify your code currently streaming the space-character.
Alternatively, write your own stream-buffer which translates it as you wish, into newline.
Sure this is possible, as I have tested. It should be portable since you are specifying an override of a templated function operator<<() included from <iostream>. The " " string in your code is not a std::string, but rather a C-style string (i.e. a const char *). The following definition works correctly:
ostream& operator << (ostream& os, const char *str) {
if(strcmp(str, " ") == 0) {
os << '\n';
} else {
// Call the standard library implementation
operator<< < std::char_traits<char> > (os, str);
}
return os;
}
Note that the space after std::char_traits<char> is necessary only if you are pre-c++11.
Edit 1
I agree with Deduplicator that this is a potentially dangerous solution as it may cause undesirable consequences elsewhere in the code base. If it is needed only in the current file, you could make it a static function (by putting it within an unnamed namespace). Perhaps if you shared more about the specifics of your problem, we could come up with a cleaner solution for you.
You might want to go with a user defined literal, e.g.
struct NewLine {};
std::ostream& operator << (std::ostream& os, NewLine)
{
return os << "\n";
}
NewLine operator ""_nl(const char*, std::size_t) // "nl" for newline
{
return {};
}
This can be used as follows.
int main(int, char **)
{
std::cout << 42 << ""_nl << "43" << ""_nl;
return 0;
}
Note three things here:
You can pass any string literal followed by the literal identifier, ""_nl does the same thing as " "_nl or "hello, world"_nl. You can change this by adjusting the function returning the NewLine object.
This solution is more of an awkward and confusing hack. The only real use case I can imagine is pertaining the option to easily change the behavior at a later point in time.
When doing something non-standard, it's best to make that obvious and explicit - here, the user defined literal indeed shines, because << ""_nl is more likely to catch readers' attention than << " ".
I am a learning c++ and have a class project due in 5 days. I've spent 4 hours researching how to do this however I have not come up with an answer yet. Save me stack!
Problem. I have a pointer to a class which holds a dynamic array. I need to take that array and save it to a file to retrieve later. Here are my 2 headers and the implementation. I am not writing the code to "save to file" yet as that will be easy once I get around this issue. My problem is it keeps printing the address of the pointer and not the data within.
vehReg.h
class vehReg {
public:
/* STUFF */
};
}
#endif
vehData.h
#include "vehReg.h"
using namespace std;
class vehData {
public:
//CONSTRUCTORS
vehData();
//DECONSTRUCTOR
~vehData();
//METHODS
friend ostream &operator<<( ostream &output, const vehData &v);
private:
typedef unsigned long longType;
typedef std::size_t sizeType;
sizeType used,capacity;
vehReg *data;
};
}
#endif
vehData.cpp
//CONSTRUCTOR
vehData::vehData(){
capacity = 5;
used = 0;
data = new vehReg[capacity];
}
//DECONSTRUCTOR
vehData::~vehData(){
delete []data;
}
/* TRYING TO ACCOMPLISH THIS WITH AN OSTREAM OVERLOAD */
void vehData::saveDataSloppy(){
ofstream myFile;
myFile.open ("database.db");
for(int i=0;i<used;i++){
myFile << data[i].getOwnerName() << "|";
myFile << data[i].getVehicleLicense() << "|";
myFile << data[i].getVehicleMake() << "|";
myFile << data[i].getVehicleModel() << "|";
myFile << data[i].getVehicleYear() << "\n";
}
myFile.close();
}
void vehData::saveData(){
cout << data;
}
ostream &operator<<(ostream &stream, const vehData &v){
stream << v.data;
}
}
v.data is a pointer, so it prints a pointer. How do you want it to
print whatever the pointer points to. With the exception of character
pointers, the << always prints what you give it (formatted in some
way). If you don't want it to print a pointer, give is something else.
Suppose it did dereference the pointer. What should it print: one
vehReg? 20? A pointer has no information concerning the size. If
you'd used std::vector<vehReg> (a much better choice), it would know
the size, but there's still no overload on std::vector, since the
system still doesn't know how you want it formatted (comma separated?
each on a new line?). And you've not told it how to print a vehReg
either.
You apparently understand the idea of how to overload <<. The first
thing you'll have to do is provide an overload for vehReg as well.
And both overloads must be defined in terms of existing overloads:
there's not one for std::vector, and the one for pointer doesn't do
what you want (and couldn't), so you'll have to loop in your << for
vehData and output each element, with whatever separators you decide
on. (If it's each element on its own line, then you can use std::copy
and an ostream_iterator for the loop, but this may be a bit in advance
of what you've learnt so far.) And forward to the << for vehReg for
each vehReg.
v.data is a pointer so it's a memory address.
*v.data is what the pointer is pointing to (which in this case is an integer).
For example,
#include <iostream>
using namespace std;
void main () {
int *ptr;
int var = 5;
ptr = &var;
cout << ptr << endl;
cout << *ptr << endl;
system("pause");
}
First line will print out something like: 0043F930
Second line will print out: 5
This should print out the elements held in the data array.
void vehData::showStructure() const {
for (int i = 0; i < capacity: i++) {
cout << data[i];
}
cout << endl;
}
ostream& operator<<(ostream& os, const PT& p)
{
os << "(" << p.x << "," << p.y << ")";
}
PT is a structure and x , y are its members.
Can someone please explain what exactly the above line does. Can't the desired text be printed using cout?
I came across this snippet of code from this site.
It's a custom overload for operator<<.
It means you can do this:
PT p = ...;
std::cout << p << "\n";
or this:
PT p = ...;
std::stringstream ss;
ss << p << "\n";
std::cout << ss;
or lots of other useful stuff.
However, it should be noted that the code you quoted won't work properly. It needs to return os.
This provides a method of outputting the PT. Now, you can use this:
PT p;
std::cout << p;
This gets translated into a call of
operator<< (std::cout, p);
That matches your overload, so it works, printing the x and y values in brackets with less effort on the user's part. In fact, it doesn't have to be cout. It can be anything that "is" a std::ostream. There are quite a few things that inherit from it, meaning they are std::ostreams as well, and so this works with them too. std::ofstream, for file I/O, is one example.
One thing that the sample you found doesn't do, but should, though, is return os;. Without doing that, you can't say std::cout << p << '\n'; because the result of printing p will not return cout for you to use to print the newline.
It allows the << operator to append the PT object to the stream. It seems the object has elements x and y that are added with a comma separator.
This operator << overloading for outputing object of PT class .
Here:
ostream& operator<<(ostream& os, const PT& p)
First param is for output stream where p will be appended.
It returns reference to os for chaining like this:
cout << pt << " it was pt" << endl;
I have a problem in my code which i can't understand. I want to make a list of lists and use it like a two-dimensional associative array.
Something like this:
token["window"]["title"] = "Amazing!";
cout << token["window"]["title"]; //Amazing!
The second line works good. Data is readed from file. Problem is with the first instruction.
This is how i overload the second square brakcets:
TokenPair Token::operator[](string keyName){
for( list<TokenPair>::iterator pair=keys.begin(); pair != keys.end();++pair){
if(pair->key == keyName){
return *pair;
}
}
}
As you see I return object of class TokenPair. To properly get the value from object (field TokenPair::value) i overload streaming and casting on string().
TokenPair::operator string() const{
return value;
}
ostream & operator<< (ostream &stream, const TokenPair &pair){
return stream << pair.value;
}
And as i say before getting value works great. Problem is with overloading operator of attribution:
TokenPair TokenPair::operator=( const string newValue ){
value = newValue;
return *this;
}
This method assing the value but it not remember that! For example:
token["window"]["title"] = "Ok";
will cause that inside method TokenPair::operator= variable newValue=="Ok" and after the first line even value is set to "Ok"; But when i later do:
cout << token["window"]["title"] ;
the field in TokenPair is still not changed. I want to ask: Why? Maybe iterators return a copy of that object? I don't know. Please help.
Your problem is that the operator[] returns a TokenPair by value, so when assigning you assign the new value to a temporary, not to the object stored in the list.
For this to work the operator[] should return a reference to the object you want to modify.
Here is an example of how to use a map-of-maps:
#include <map>
#include <string>
#include <iostream>
#include <sstream>
const char inputString[] =
"President 16 Lincoln "
"President 1 Washington "
"State Best Illinois "
"State Biggest Alaska ";
int main () {
std::map<std::string, std::map<std::string, std::string> > token;
std::string primary, secondary, result;
std::istringstream input(inputString);
while( input >> primary >> secondary >> result )
token[primary][secondary] = result;
std::cout << "Abe " << token["President"]["16"] << "\n";
std::cout << "Springfield, " << token["State"]["Best"] << "\n";
std::cout << "Blank: " << token["President"]["43"] << "\n";
}
Newbie programmer here trying to work out his homework. I'm trying to use a STL set of classes, but the compiler complains about my code.
car.h
#include <string>
#include <iostream>
#include <time.h>
#include <set>
class Car
{
private:
std::string plateNumber;
std::string description;
std::string dateIn;
std::string timeIn;
public:
Car() {};
~Car() {};
Car(std::string plate, std::string desc)
{
plateNumber = plate;
description = desc;
};
void setPlateNumber(std::string plate) ;
std::string getPlateNumber() const;
void setDesc(std::string desc);
void setTimeDateIn() ;
std::string getTimeIn() const;
std::string getDateIn() const;
std::string getDesc() const;
friend std::ostream & operator<<(std::ostream & os, Car &c);
};
std::ostream & operator<<(std::ostream & os, Car& c)
{
os << "Plate Number: " << c.plateNumber << ", Date In: " << c.dateIn << ", " <<
`"Time in: " << c.timeIn << "Description: " << c.description << std::endl;
return os;
}
bool operator< ( const Car& lhs, const Car& rhs)
{
return ( lhs.getPlateNumber() < rhs.getPlateNumber() );
};
main.cpp
#include "stdafx.h"
#include <iostream>
#include <set>
#include <string>
#include "car.h"
void carEnters(std::set<Car> g);
void carLeaves(std::set<Car> g);
void displayContents(std::set<Car> g);
int main ()
{
char choice [80];
// initialize the sets and iterators
std::set<Car> garage;
do // Loop until user quits
{
std::cout <<
std::endl;
std::cout << "Menu:" << std::endl;
std::cout << "-----" << std::endl;
std::cout << "'1' to enter a new car, or " << std::endl;
std::cout << "'2' to exit the front car, or " << std::endl;
std::cout << "'3' to to list all the cars or." << std::endl;
std::cout << "'0' to close the garage: " << std::endl;
std::cin.getline( choice, 1, '\n');
switch ( choice[0] )
{
case '0' :
std::cout << std::endl << "Thanks for playing...\n";
break;
case '1' :
carEnters(garage);
break;
case '2' :
carLeaves(garage);
case '3' :
displayContents(garage);
break;
default:
std::cout << "I'm sorry, I didn't understand that.\n";
break;
}
} while ( choice[0] != '0' ); // Loop again if the user hasn't quit.
return 0;
}
void carEnters( std::set<Car> g)
{
// Car enters garage
std::cout << "Please enter the plate number:" << std::endl;
std::string plate;
std::cin >> plate;
std::cin.ignore();
std::set<Car>::iterator findPlate;
Car* lookup = new Car;
lookup->setPlateNumber(plate);
findPlate = g.find(*lookup);
if (findPlate != g.end()) // Add car to garage
{
Car *currentCar = new Car ;
// Set car parameters
std::cout << "Please type the entering car's description <Model, Color...
> : " << std::endl;
char desc[80];
std::cin.get(desc, 80 );
std::cin.ignore();
currentCar->setDesc(desc);
currentCar->setTimeDateIn();
currentCar->setPlateNumber(plate);
g.insert(currentCar);
}
else // Plate is already in garage set
{
std::cout << "Sorry, this car is already in the garage!" <<
std::endl;
}
}
void carLeaves( std::set<Car> g)
{
std::string plate;
std::cout << "Which plate is leaving?" << std::endl;
std::cin >> plate;
std::cin.ignore();
// Find car's plate number in the garage set
// for (findPlate=garageSet.begin(); findPlate !=garageSet.end(); findPlate++)
std::set<Car>::iterator findPlate;
Car lookup(plate,"");
findPlate = g.find(lookup);
if (findPlate != g.end())
{
// Display time in and then remove car from set of cars
std::cout << "Car out at " << (*findPlate).getDateIn() << ", " <<
(*findPlate).getTimeIn() << std::endl;
g.erase(findPlate);
}
else
{
std::cout << "Car was not found in set of Cars!" << std::endl;
}
}
// Car class function implementation
void Car::setPlateNumber(std::string p)
{
plateNumber = p;
}
std::string Car::getPlateNumber() const
{
return plateNumber;
}
void Car::setDesc(std::string d)
{
description = d;
}
void Car::setTimeDateIn()
{
char dat[9];
char tim[9];
_strdate_s(dat);
_strtime_s(tim);
dateIn=dat;
timeIn=tim;
}
std::string Car::getTimeIn() const
{
return timeIn;
}
std::string Car::getDateIn() const
{
return dateIn;
}
std::string Car::getDesc() const
{
return description;
}
// Display the car set
void displayContents(std::set <Car> garage)
{
// function displays current contents of the parking garage.
std::set <Car>::iterator carIndex;
std::cout << std::endl << "Here are all the cars parked: " << std::endl;
for (carIndex = garage.begin();
carIndex != garage.end();
++carIndex )
{
std::cout << " " << carIndex->getPlateNumber() << ", Date In: " <<
carIndex->getDateIn() << ", " << "Time In: " << carIndex->getTimeIn() << "Description:
" << carIndex->getDesc() << std::endl;
}
}
The error I get from the compiler is this:
xmemory(208): error C2664: 'Car::Car(const Car &)' : cannot convert parameter 1 from 'Car *' to 'const Car &'
Reason: cannot convert from 'Car *' to 'const Car'
No constructor could take the source type, or constructor overload resolution was ambiguous
I'm not sure where I'm going wrong, would some please point out how my overload is incorrect?
Thanks
The error is likely the g.insert(currentCar) line in the carEnters method, as g is a std::set<Car>, not a std::set<Car*>. Either pass in a reference to the current car (*currentCar) or make the garage contain pointers to cars.
In addition, you may wish to pass in g as a reference, in the form of...
void carEnters(std::set<Car>& g) { }
void carLeaves(std::set<Car>& g) { }
Otherwise the set is being copied and you might not get the results you want.
If you need explanation as to the why for any of these, add a comment. I used to do some TAing back in the day. :)
I believe #James is on the right track, but passing *CurrentCar isn't really the right answer (at least IMO). Instead, you should back up a bit:
Car *currentCar = new Car ;
Perhaps you have prior experience with Java (or something similar) where this is a routine, normal type of code to write. In C++, however, using new directly is (or at least should be) fairly unusual. What you almost certainly want instead is:
Car currentCar;
and then you'll fill in the fields like:
currentCar.whatever = x;
Then, when you put your currentCar into the std::set (or whatever) you won't have to dereference anything, because you'll be starting with a Car object, which is what's expected. As an aside, I'd note that when you look up the car, you're also creating a Car object dynamically -- but you never seem to delete either one, so you're code is leaking memory.
Edit: I should add that there are alternatives that may be preferable. Right now, you're basically treating a Car as "dumb data", with outside code to operate on that data. If you want your code to be "object oriented", it would almost certainly be better to move the code for reading a Car's data into the class itself, so outside code would just invoke that member function.
Another possibility would be to make a Car an immutable object. Instead of creating an unitialized car, and then setting the appropriate values in that object, I'd pass the correct values to Car's constructor, and eliminate the member functions you currently have for changing those values. At least for your purposes, it doesn't appear that you need to actually change a car's plate number -- it should apparently only ever have one plate number, in which case it would be better for your code to reflect (and enforce) that directly.
Your problem is that your set takes elements of type Car but you are inserting elements of type Car*:
void carEnters( std::set<Car> g)
{
...
Car *currentCar = new Car;
...
g.insert(currentCar);
In this case, currentCar is a pointer to a Car and g.insert expects a Car. There are multiple ways of fixing this - you can change your set to use Car* although your overloaded operator< will no longer work (you'll have to create a functor that is passed to the set and takes two Car*s). You can change currentCar to be of type Car. This results in a bunch of copying however. Or you can ditch currentCar entirely and make a constructor that will set all the variables you need set:
Car(const std::string &plate, const std::string &desc)
{
plateNumber = plate;
description = desc;
setTimeDateIn();
};
then you can just do this:
g.insert(Car(desc, plate));
Which is actually preferable to what you are doing now, as someone might forget to call setTimeDateIn. It makes more sense for that to be called when the Car is constructed.