EDIT: Passed Expression exp and string expression by const reference
I'm trying to allow a class to be display via cout in the following manner:
#include <iostream>
class Expression {
private:
std::string expression;
public:
Expression(const std::string& expression):
expression(expression) { }
friend std::ostream& operator <<(ostream& os, const Expression& exp) {
return os << exp.expression; }
};
however, on compiling I get the errors:
main.cpp(9) : error C2061: syntax error : identifier 'ostream'
main.cpp(9) : error C2809: 'operator <<' has no formal parameters
this is especially confusing because VC++ is giving me ostream as an autocompletion suggestion when I enter std::. What's causing these errors, and how can they be resolved?
Surely you need std::ostream in all locations? i.e.:
friend std::ostream& operator <<(std::ostream& os, Expression& exp) ...
^^^
Without a using namespace std; clause (which has its own set of problems), you need to fully qualify all the iostream stuff.
You can see this with the following program:
#include <iostream>
class Expression {
private:
std::string expression;
public:
Expression(std::string expression):
expression(expression) { }
// added this bit.
// _/_
// / \
friend std::ostream& operator <<(std::ostream& os, Expression& exp) {
return os << exp.expression; }
};
int main (void) {
Expression e ("Hi, I'm Pax.");
std::cout << e << std::endl;
return 0;
}
which prints out:
Hi, I'm Pax.
as expected.
And, as some comments have pointed out, you should pass the string as const-reference:
#include <iostream>
class Expression {
private:
std::string expression;
public:
Expression(const std::string& expression)
: expression(expression) {
}
friend std::ostream& operator <<(std::ostream& os, const Expression& exp) {
return os << exp.expression;
}
};
int main (void) {
Expression e ("Hi, I'm Pax.");
std::cout << e << std::endl;
return 0;
}
Related
The code:
catch (test& t)
{
cout << t /*error here*/<</*to here*/ " is not a positive number";
}
causes an error:
No operator "<<" matches these operands
The compiler (c++ 20) says that the error is the << between t and " is not a positive number". It might be caused because I overloaded the operator wrong?
Here's my operator << overload:
ostream& operator << (ostream& os, const test& t)
{
os << t.getX(); //getX is just a method for getting private member
return os;
}
The entire code, if this isn't enough:
class test
{
int x;
public:
explicit test(const int _x)
{
x = _x;
}
int getX() const
{
return x;
}
friend test& operator << (ostream&, test&);
};
ostream& operator << (ostream& os, const test& t)
{
os << t.getX();
return os;
}
auto main() -> int
{
int n;
cin >> n;
try
{
if (n < 0)
{
throw test(n);
}
}
catch (test& t)
{
cout << t /*error here*/ <</*to here*/ " is not a positive number";
}
}
You have declared one operator<<, and defined a different one. And the wrongly-formed one turns out to be the best match.
Replace* this, which you have declared in your class:
test & operator << (ostream & , test & )
With this, which you have defined:
ostream & operator << (ostream & os, const test & t)
Edit:
*An astute observation from the frequently-astute Mark Ransom:
The bad declaration isn't needed at all. The function doesn't need to be declared friend. That declaration could simply be removed.
The friend modifier is required if you declare operator overloading as a class/structure member. In the case of declaring globally, it is not necessary indeed!
First option:
class test {
int x;
public:
explicit test(const int _x) { x = _x; }
int getX() const { return x; }
};
std::ostream& operator<<(std::ostream& os, const test &t) {
os << t.getX();
return os;
}
Second option:
class test {
int x;
public:
explicit test(const int _x) { x = _x; }
int getX() const { return x; }
friend std::ostream& operator<<(std::ostream& os, const test &t) {
os << t.getX();
return os;
}
};
I have learnt the operator<< can be overloaded by making it a friend function of class.
For example,
struct Test
{
std::string d_data;
Test(const std::string & data) : d_data{data} {}
friend std::ostream & operator<<(std::ostream & ostr, const Test & obj)
{
ostr << obj.d_data << '\n';
return ostr;
}
};
int main()
{
Test t1("one");
std::cout << t1;
Test t2("two");
std::cout << t2;
}
one
two
This seems to work as expected.
But, I'm unable to understand why the same isn't working for a global overload.
#include <iostream>
#include <ostream>
#include <string>
std::ostream & operator<<(std::ostream & os, const std::string & s)
{
os << s << '\n';
return os;
}
int main()
{
std::cout << "stackoverflow";
std::cout << "stackoverflow";
}
stackoverflowstackoverflow
Expected the strings to be separated by a newline, but didn't work as expected.
Your operator using
std::cout << "stackoverflow";
requires a user-defined conversion from an object of the type const char * (after the implicit conversion of the string literal to pointer to its first character) to an object of the type std::string.
However the standard basic_ostream class has already an operator that does not require such a conversion
template<class charT, class traits>
basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>&, const char*);
So this operator is called instead of your operator.
Moreover within your operator
std::ostream & operator<<(std::ostream & os, const std::string & s)
{
os << s << '\n';
return os;
}
there is recursive calls of itself.
Your could define your operator the following way
#include <iostream>
#include <string>
std::ostream & operator<<(std::ostream & os, const char *s)
{
return std::operator <<( os, s ) << '\n';
}
int main()
{
std::cout << "stackoverflow";
std::cout << "stackoverflow";
}
and get the expected result
stackoverflow
stackoverflow
Note that "stackoverflow" is of type const char[], but not std::string. That means your overload won't be invoked, but the one from standard library (operator<<(std::basic_ostream) is invoked, because it's an exact match and doesn't require the implicit conversion from const char[] to std::string.
template< class Traits >
basic_ostream<char,Traits>& operator<<( basic_ostream<char,Traits>& os,
const char* s );
BTW: It could be found because of ADL.
You can overload globally, but "stackoverflow" is not a std::string, so yours isn't used.
(And there already is such an overload in the standard library.)
To see that it works, move your first overload out of the class definition and make it a non-friend.
The only reason it has to be declared friend is that you have declared it inside the class definition, so it would be a member function otherwise.
This will work as you expect:
struct Test
{
std::string d_data;
Test(const std::string & data) : d_data{data} {}
};
std::ostream & operator<<(std::ostream & ostr, const Test & obj)
{
ostr << obj.d_data << '\n';
return ostr;
}
int main()
{
Test t1("one");
std::cout << t1;
Test t2("two");
std::cout << t2;
}
Lets say i have a class, for which i want to overload an operator based on an enum type:
#include <iostream>
enum class option : char { normal, do_something_stupid };
class foo
{
public:
int i;
explicit foo(int a=0) : i(a) {};
/* overload operator '+=' based on 'option' */
template<option E = option::normal>
void operator+=(const foo& f) { i += f.i; }
};
/* explicit specialization for operator += */
template<> void foo::operator+=<option::do_something_stupid>(const foo& f)
{ i += (f.i +1000); }
int main()
{
foo f1(1), f2(2);
f1 += f2;
std::cout << "\nf1 = " << f1.i;
f1.operator+=<option::do_something_stupid>(f2);
std::cout << "\nf1 = " << f1.i;
std::cout << "\n";
return 0;
}
This builds clean (ignoring the fact that it really does something pretty dump) both on g++ and clang++.
What if i want to overload the '<<' operator the same way? A similar approach does not seem to work:
#include <ostream>
#include <iostream>
enum class option : char { normal, do_something_stupid };
class foo
{
public:
int i;
explicit foo(int a=0) : i(a) {};
template<option E = option::normal>
friend std::ostream& operator<<(std::ostream& o, const foo& f)
{ o << f.i; return o; }
};
template<> std::ostream&
operator<< <option::do_something_stupid>(std::ostream& o, const foo& f)
{
o << f.i + 1000;
return o;
}
int main()
{
foo f1(1), f2(2);
std::cout << "\nf1= " << f1;
std::cout << "\nf2= ";
/* this triggers an error with g++ */
std::cout.operator<< <option::do_something_stupid>(f1);
std::cout << "\n";
return 0;
}
According to g++, the call from main to the operator is invalid:
error: no match for ‘operator<’ (operand types are ‘<unresolved overloaded function type>’ and ‘option’)
std::cout.operator<< <option::do_something_stupid>(f1);
clang++ on the other hand, produces a different error message:
lsfov.cc:20:1: error: 'operator<<' cannot be the name of a variable or data member
operator<< <option::do_something_stupid>(std::ostream& o, const foo& f)
^
lsfov.cc:20:11: error: expected ';' at end of declaration
operator<< <option::do_something_stupid>(std::ostream& o, const foo& f)
^
;
lsfov.cc:20:12: error: expected unqualified-id
operator<< <option::do_something_stupid>(std::ostream& o, const foo& f)
^
lsfov.cc:33:15: error: reference to non-static member function must be called
std::cout.operator<< <option::do_something_stupid>(f1);
~~~~~~~~~~^~~~~~~~~~
which goes on listing possible overload of '<<' from the standard library (if i understand correctly), like:
/usr/bin/../lib/gcc/x86_64-redhat-linux/5.3.1/../../../../include/c++/5.3.1/ostream:108:7: note: possible target for call
operator<<(__ostream_type& (*__pf)(__ostream_type&))
^
/usr/bin/../lib/gcc/x86_64-redhat-linux/5.3.1/../../../../include/c++/5.3.1/ostream:117:7: note: possible target for call
operator<<(__ios_type& (*__pf)(__ios_type&))
^
What is going on? Is this kind of operator specialization possible/allowed? If so, what is the proper way to call the operator? Or is clang correct and the definition is ill formed?
I think clang doesn't like the declaration of the friend in relation to the specialisation. Re-ordering them does the trick.
enum class option : char { normal, do_something_stupid };
// forward declare the class and operator
class foo;
template<option E = option::normal>
std::ostream& operator<<(std::ostream& o, const foo& f);
// the class with the declared friend operator
class foo
{
private:
int i;
public:
explicit foo(int a=0) : i(a) {};
template<option E>
friend std::ostream& operator<<(std::ostream& o, const foo& f);
};
// the operator implementations
template<option E>
std::ostream& operator<<(std::ostream& o, const foo& f)
{ o << f.i; return o; }
template<> std::ostream&
operator<< <option::do_something_stupid>(std::ostream& o, const foo& f)
{
o << f.i + 1000;
return o;
}
In addition, the operator<< used in the main is not a member cout, but rather a global.
int main()
{
foo f1(1), f2(2);
std::cout << "\nf1= " << f1;
std::cout << "\nf2= ";
/* this triggers an error with g++ */
operator<< <option::do_something_stupid>(std::cout, f1);
std::cout << "\n";
return 0;
}
Sample here. g++ is also happy with the code as above.
A note on operators in a non-deduced context. I assume you are using the code here in a greater project of some sort, but if the operator is being used with non-deduced parameters, it is often easier and clearer to implement the functionality in a member method or a free function (using friend as required).
For example, I've written a class called Length:
class Length {
public:
void setValue(float);
private:
float value_;
};
void
Length::setValue(float newValue) {
value_ = newValue;
}
void print(float value) {
std::cout << value;
}
void computeStuff(float value) {
//do the computing
}
int main() {
Length width;
width.setValue(5);
std::cout << width; // <-- this is actually just an example
//what I actually want is:
print(width); // print 5
//or perhaps even
computeStuff(width);
return 0;
}
Now how to make width return value_ or 5?
Technically, width is not an instance name, it's a name of a variable of type Length. You can change your code to retrieve a variable in two ways:
Add a friend operator << for Length that does the printing, or
Add an implicit conversion operator from Length to float.
The first approach works only for output. You cannot pull the value directly:
friend ostream& operator <<(ostream& out, const Length& len) {
out << len.value_;
return out;
}
The second approach looks like this:
class Length {
...
public:
operator float() const { return value_; }
};
You must overload operator<< for your custom type, something like:
class Length
{
..
friend std::ostream& operator<<(std::ostream& os, const Length& o);
..
}
std::ostream& operator<<(std::ostream& os, const Length& o)
{
os << o.value_;
return os;
}
Mind that this
must be non member
is nothing special , just an operator overload applied to a standard way of inserting things into stream of <iostream>
You need to define an operator() method to print the value 5.
You need to overload the << operator for your class. You could also use a function to do the operator's work.
Operator <<
#include <iostream>
class Length {
friend std::ostream& operator<<(std::ostream& os, const Length& l);
public:
void setValue(float);
private:
float value_;
};
void
Length::setValue(float newValue) {
value_ = newValue;
}
std::ostream& operator<<(std::ostream& os, const Length& l)
{
os << l.value_;
return os;
}
int main() {
Length width;
width.setValue(5);
std::cout << width << std::endl; // print 5
return 0;
}
function:
#include <iostream>
class Length {
friend std::ostream& print(std::ostream &,const Length &l);
public:
void setValue(float);
private:
float value_;
};
void
Length::setValue(float newValue) {
value_ = newValue;
}
std::ostream& print(std::ostream &os, const Length &l)
{
os << l.value_;
return os;
}
int main() {
Length width;
width.setValue(5);
print(std::cout, width) << std::endl;
return 0;
}
I am trying to use boost::lexical_cast to convert my user defined type into an integer.
However, I get an exception. What am I missing??
class Employee {
private:
string name;
int empID;
public:
Employee() : name(""), empID(-1)
{ }
friend ostream& operator << (ostream& os, const Employee& e) {
os << e.empID << endl;
return os;
}
/*
operator int() {
return empID;
}*/
};
int main() {
Employee e1("Rajat", 148);
int eIDInteger = boost::lexical_cast<int>(e1); // I am expecting 148 here.
return 0;
}
I know I can always use the conversion operator, but just wondering why lexical cast doesn't work here.
The problem is that what you insert into the output stream is not the representation of an integer (because of the trailing << std::endl). The following fails in a similar way:
boost::lexical_cast<int>("148\n")
Removing the << std::endl makes it work:
friend std::ostream& operator << (std::ostream& os, const Employee& e) {
os << e.empID;
// ^^^^^^^^^^^^^^
// Without << std::endl;
return os;
}