Overloading the ostream operator yields compile errors - c++

Hi all I have this code -
typedef struct signal_declairation{
//these are for 2001 type declairation
bool is_array;
int array_start, array_end;
PORT_ATTRIBUTE port_attribute; //port direction
string port_type; //logic, UDT, wire, accept every thing
//this is common to 2001 and normal
string port_name;
//dumper method
friend ostream& operator<<(ostream &out, signal_declairation &m_signal_declairation);
} SIGNAL_DECLAIRATION;
std::ostream& operator<< (ostream &out, signal_declairation &m_signal_declairation)
{
string port_direction;
switch(m_signal_declairation.port_attribute){
case INPUT: port_direction = "input";
break;
case OUTPUT: port_direction = "output";
break;
case INOUT: port_direction = "inout";
break;
}
if(m_signal_declairation.is_array==true){
out << " Port Name = " << m_signal_declairation.port_name
<< " Port Direction = " << m_signal_declairation.port_attribute
<< " Port type = " << m_signal_declairation.port_type
<< " This is an arrayed port :: Array Start = " << m_signal_declairation.array_start
<< " Array End = " << m_signal_declairation.array_end ;
}else{
out << " Port Name = " << m_signal_declairation.port_name
<< " Port Direction = " << m_signal_declairation.port_attribute
<< " Port type = " << m_signal_declairation.port_type;
}
return out;
}
When I try and compile, I get errors that look like this -
parser_globals.h: In function ‘std::ostream& operator<<(std::ostream&,
signal_declairation&)’: parser_globals.h:53:9: error: no match for
‘operator<<’ (operand types are ‘std::ostream {aka
std::basic_ostream}’ and ‘const char [14]’)
out << " Port Name = " << m_signal_declairation.port_name
Not sure why I am not able to pass class members to << as shown above. Can anyone help ????
Thanks
Raj

If you had provided the complete error messages that you get and not just a small snippet, things would have been easier.
Based on what you provided so far, it looks like you might have forgot to include the necessary header(s) for the standard streams, e.g.:
#include <iostream>
This would cause the compiler to not find the operator<< overloads for the base types or the types from the standard library.

change your overload definition :
std::ostream& operator<< (ostream &out, signal_declairation &m_signal_declairation)
by std::ostream& operator<< (ostream &out,const signal_declairation &m_signal_declairation) .
Dont forget the prototype too.

The compiler complains about the ‘const char [14]’) out << " Port Name = ". It looks like the compiler cannot see the " Port Name - " as string, rather it sees it as character array. Have you include ?

Related

Overload << operator to change " " to "\n"

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 << " ".

Why doesn`t operator<< work successfully?

While compiling the below code, I am getting an error:
Expression.h
class Expression{
...
protected:
std::ostream Os;
};
Expression.c
Expression::Expression() : Os(std::cout)
{
...
}
Expression::Expression(std::ofstream &os) : Os(os)
{
...
}
Expression::Dump()
{
Os << "=============================================================" << std::endl;
Os << "Os: " << Os << std::endl;
}
error: no match for 'operator<<' (operand types are 'std::basic_ostream<char>' and 'std::ostream {aka std::basic_ostream<char>}')
What is my mistake? What should I do to fix it?
And while giving initial value to parameter like this Os(std::cout), what does it mean?
Consider
Os << "Os: " << Os << std::endl;
Let us unpack it into its full functional glory:
std::ostream& t1 = Os.operator <<("Os: ");
std::ostream& t2 = t1.operator <<(Os); // << Here
std::ostream& t3 = t2.operator <<(std::endl);
The problem is the line marked "Here". You are streaming an ostream to itself. This is nonsensical. What are you trying to do?
If you are trying to output an identifier for the stream, you should use the address:
Os << "Os: " << &Os << std::endl;
If you are trying to output the contents of the stream to stdout, you need to make Os be an ostringstream, and then output the string buffer:
std::ostringstream Os;
...
std::stdout << "Os: " << Os.str() << std::endl;
Note for the pedantic: I believe my breakdown of the original line into function calls and initializations is actually identical in this particular case (because there are no temporary objects - only references); in general, the lifetime of temporaries might be subtly different.
The error is because there is no standard operator<< that writes an ostream to another ostream.
Also, ostream can't be copy-constructed from another ostream, so if you are trying to specify an output ostream for Expression to write to then your Os member needs to be declared as a reference instead.
class Expression {
...
protected:
std::ostream &Os;
};
Expression::Expression() : Os(std::cout)
{
...
}
Expression::Expression(std::ofstream &os) : Os(os)
{
...
}
Expression::Dump()
{
Os << "=============================================================" << std::endl;
Os << "Os: " << SomethingThatIsNotOs << std::endl;
}

No match for 'operator<<' in std::cout [duplicate]

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.

C++ Overloading operator<< outputs address

So in my program I have some classes - Button, Window and WindowButton. Button consists only of text, Window - of a button and coordinates(x,y), and WindowButton consists of a Window.
In WindowButton, I have overloaded the << operator like this:
ostream& operator<<(ostream& out, WindowButton& ref)
{
ref.print();
return out;
}
Where the print function looks like:
void WindowButton::print()
{
theWindow->print();
}
And the window print function, in window class:
void Window::print()
{
char* buttonText = button->getText();
char* theText = new char[strlen(buttonText)+1];
strcpy(theText, buttonText);
cout << endl << "Window with coordinates (" << this->coord.x << "," << this->coord.y << ") , and button text \"" << theText << "\"" << endl;
}
In main:
WindowButton *test = new WindowButton();
cout << endl << test;
test->print();
The last line provides the right output, but the second line provides just a memory adress. What am I doing wrong? Everything should be working fine, because the test->print(); works fine.
You are passing a pointer to operator<< which expects a &.
cout << endl << *test;
You might also make it:
ostream& operator<<(ostream& out, const WindowButton& ref){
Which assumes print doesn't actually modify.
But, the bigger question is why are you using the cout ostream to trigger printing to theWindow -- these appear to be (though aren't) logically disconnected processes. You could pass the given stream into Window::print:
void Window::print(ostream& stream) {
and use that stream in place of cout. This avoids hard-coding cout into Window::print().
It's a pointer, so you'll need to dereference it for the operator to work:
cout << endl << *test;
This line
cout << endl << test;
prints a pointer to WindowButton, and there is an ostream& operator<< specialization for pointers, which prints the address. You can try de-referencing the pointer:
cout << endl << (*test);
As an aside, there is little point in overloading the ostream& operator<< in a way that eventually just prints to std::cout. The point of such an operator is that you can stream to any ostream, not just cout. You could fix this by modifying your print functions to take an ostream by reference, and modify it:
void WindowButton::print(std::ostream& out) const {
theWindow->print(out);
}
and
void Window::print(ostream& out) const {
// stuff
out << "Window with coordinates (" << this->coord.x << "," << this->coord.y << ") , and button text \"" << theText << "\"" << endl;
}
and finally
ostream& operator<<(ostream& out, const WindowButton& ref){
ref.print(out);
return out;
}

Compiler error message with cout

I mistyped the error message before. It is fixed now.
I'm currently getting the following compiler error message
error: no match for 'operator<<' in 'std::cout << Collection::operator[](int)(j)'
The code that the compiler is complaining about is
cout << testingSet[j];
Where testingSet is an object of type Collection that has operator[] overloaded to return an object of type Example. Example has a friend function that overloads operator<< for ostream and Example.
note: this actually compiles just fine within Visual Studio; however does not compile using g++.
Here is the implementation of operator<<:
ostream& operator<<(ostream &strm, Example &ex)
{
strm << endl << endl;
strm << "{ ";
map<string, string>::iterator attrib;
for(attrib = ex.attributes.begin(); attrib != ex.attributes.end(); ++attrib)
{
strm << "(" << attrib->first << " = " << attrib->second << "), ";
}
return strm << "} classification = " << (ex.classification ? "true" : "false") << endl;
}
And the operator[]
Example Collection::operator[](int i)
{
return examples[i];
}
Probably your operator should be declared as:
ostream& operator<<(ostream &strm, const Example &ex)
Note the const-reference to Example.
Visual Studio has an extension that allows to bind a reference to a non-const r-value. My guess is that your operator[] returns an r-value.
Anyway, an operator<< should be const as it is not expected to modify the written object.