#include "stdafx.h"
#include "Record.h"
template<class T>//If I make instead of template regular fnc this compiles
//otherwise I'm getting an error (listed on the very bottom) saying
// that operator << is ambiguous, WHY?
ostream& operator<<(ostream& out, const T& obj)
{
out << "Price: "
<< (obj.getPrice()) << '\t'//this line causes this error
<< "Count: "
<< obj.getCount()
<< '\n';
return out;
}
int _tmain(int argc, _TCHAR* argv[])
{
vector<Record> v;
v.reserve(10);
for (int i = 0; i < 10; ++i)
{
v.push_back(Record(rand()%(10 - 0)));
}
copy(v.begin(),v.end(),ostream_iterator<Record>(cout, "\n"));
return 0;
}
//Record class
class Record
{
private:
int myPrice_;
int myCount_;
static int TOTAL_;
public:
Record(){}
Record(int price):myPrice_(price),myCount_(++TOTAL_)
{/*Empty*/}
int getPrice()const
{
return myPrice_;
}
int getCount()const
{
return myCount_;
}
bool operator<(const Record& right)
{
return (myPrice_ < right.myPrice_) && (myCount_ < right.myCount_);
}
};
int Record::TOTAL_ = 0;
Error 2 error C2593: 'operator <<' is ambiguous
The concept behind operator<<( ostream &, ... ) is that every class can have its own overload, handling that specific class in a way that make sense.
That means you get operator<<( ostream &, const Record & ) which handles Record objects, and operator<<( ostream &, const std::string & ) which handles standard strings, and operator<<( ostream &, const FooClass & ) which handles FooClass objects. Each of these functions knows how to handle the object type it has been declared for, because each of them requires a different handling. (E.g. getPrice() / getCount() for Record, or getFoo() / getBar() for FooClass.)
Your template is trampling roughshod over the whole concept. By defining it as a template function (which would match any class), you not only collide with the many definitions of operator<<() already in the standard / your codebase, but all possible overloadings.
How could the compiler decide whether to use operator<<( ostream &, const std::string & ) or your template? It cannot, so it throws up its hands in despair and gives up. That's what the error is telling you.
First, you need to read the error message more carefully. As an alternative, consider breaking the statement up, something like this:
out << "Price: ";
out << (obj.getPrice());
out << "\tCount: ";
out << obj.getCount();
out << '\n';
When you do, you'll realize that what's really causing the problem is not where you try to print out getPrice(), but where you try to print out "Price: ".
The problem is arising because the compiler doesn't know whether to use the normal overload to print out the string, or to use the template being defined to print it out. The latter would cause infinite recursion, and it couldn't actually compile since it requires an object on which you can/could call getPrice and getCount to compile correctly -- but it has a signature that matches, so the compiler says it's ambiguous, and that's the end of that.
The reason of the error is that your templated overload is conflicting with another templated overload, and there is no reason to prefer one template to another:
template<class charT, class traits>
basic_ostream<charT,traits>& operator<<(basic_ostream<charT,traits>&, const charT*);
template <class T>
basic_ostream<char, char_traits<char> >& operator<< (basic_ostream<char, char_traits<char> >&, const T&);
//which one is preferable when you ask for: cout << "literal";?
(ostream should be a typedef for basic_ostream<char, char_traits<char> >.)
The whole idea of making your overload a template is questionable, seeing that the overload clearly cannot handle any other class than your Record.
There probably are techniques to allow you to provide a single templated overload for a number of unrelated Record-like classes with a little template metaprogramming (enable_if and traits), if that is the idea.
Related
I wonder, why functional objects in c++ are implemented as templated, with void as default type since c++14.
For example:
https://en.cppreference.com/w/cpp/utility/functional/plus
https://en.cppreference.com/w/cpp/utility/functional/minus
This object in fact performs arithmetic operation +, -, *, /, when called by operator().
The operator() has to be template to work with different types as arguments, but why does the struct have to be?
EDIT
I can create an operator std::plus<>, which may work with a different types in operator():
struct Foo{
int foo;
};
Foo operator+(const Foo& lhs, const Foo& rhs){
return {2 * lhs.foo + 3 * rhs.foo};
}
std::ostream& operator<<(std::ostream& os, const Foo& f){
std::cout << f.foo;
return os;
}
int main()
{
auto op = std::plus<>();
std::cout << op(5, 3) << "\n";
std::cout << op(3.14, 2.71) << "\n";
std::cout << op(Foo(2), Foo(3)) << "\n";
}
And this gives the expected output. Or it may be the case, that having specified the type initially you get something more optimized?
It's a design choice. If you specify the type there is no template operator(), instead the whole class is a template. The operator() is simply something like
constexpr T operator()(const T &lhs, const T &rhs) const
{
return lhs + rhs;
}
This is in several ways different from having a template operator().
If we pass a std::plus<int> it's a plus functor for specifically ints and nothing else.
If we instead passed a std::plus<> without specifying the type it would have a templated operator(). That functor could apply it's operator() to any valid type.
Some advantages with restricting the type from the top of my head:
Since the type is specified the functor can deal with implicit conversion without any issues.
You know for a fact that the functor is not going to silently do things we don't want it to. It's only ever going to do addition on Ts.
Edit
Some examples when the behaviour would differ.
#include <iostream>
#include <functional>
#include <string>
struct Foo {};
int main()
{
auto stringadd = std::plus<std::string>{};
auto anyadd = std::plus<>{};
std::cout << stringadd("hey ", "you") << '\n';
//std::cout << anyadd("hey ", "you") << '\n'; // error: no match for call to '(std::plus<void>) (const char [5], const char [4])'
//std::cout << stringadd("hey ", 1) << '\n'; // error: no match for call to '(std::plus<std::__cxx11::basic_string<char> >) (const char [5], int)'
std::cout << anyadd("hey ", 1) << '\n';
}
I'm trying to understand how to properly overload the "<<" operator so that I can use
std::cout << my_object;
to print useful debug messages. In particular, I need to have an implementation of << for each of my subclasses, so I'm declaring << to be virtual in the superclass.
Right now I'm stuck with the following piece of code
#include <iostream>
using namespace std;
class Shape {
public:
virtual ~Shape() { };
virtual ostream& operator<<(std::ostream &strm) = 0;
};
class Square : public Shape {
int size;
public:
Square() { size = 10; }
~Square() { }
ostream& operator<<(std::ostream &strm) {
return strm << "a square with size " << size;
}
};
int main() {
Square *my_square = new Square();
cout << "my_square is " << my_square << "\n";
}
which (I think) should be working, but doesn't. What I get when using "<<" is that the pointer value of my_square gets printed, rather than the result of the overloaded << .
$ ./a.out
my_square is 0xcacc20
What am I missing here?
operator<< can't be a member function. This is because of the order of the arguments. The stream has to come first.
When calling an overloaded operator, such as:
os << object;
the compiler will attempt to look up both
os.operator<<(object);
and
operator<<(os, object);
(The rules for this can be rather complex, I won't attempt to describe them here.)
Because the stream always comes on the left, your member function will never be found, since it would have to be called as:
object.operator<<(os);
You need to write a free function like:
ostream& operator<<(std::ostream &strm, Square const& square) {
return strm << "a square with size " << square.size();
}
(where Square::size() returns the size member).
Then you need to remember to dereference your pointer too:
std::cout << *my_square << '\n';
Although I see no reason to be dynamically allocating my_square in this example anyway. Just stick it on the stack as a local variable.
If the aim here is ultimately to be able to print any Shape&, and have the printed output follow the "real" type, you would need to create:
virtual std::ostream& print(std::ostream&) const = 0;
in the Shape base class, and override it in each derived class, then have a free function:
std::ostream& operator<<(std::ostream& os, Shape const& shape)
{
return shape.print(os);
}
It is often advised to make all binary operators on your type non-member functions, so that both arguments are treated equally, and the operation remains commutative. See Scott Meyers, Effective C++ (3rd Edition), Item 24, (or find a summary online).
As noted by others, the problem is that operator << can't be member function (because of the order of arguments). The canonical way to do this is to have operator <<(const Shape&) call a virtual function in Shape
class Shape {
friend ostream& operator<<(std::ostream& str, const Shape& shape);
virtual void do_print(ostream& str) = 0;
public:
virtual ~Shape() { };
};
ostream& operator<<(std::ostream& str, const Shape& shape) {
shape.do_print(str);
return str;
}
Note that it is legal to have do_print be private, even though it is going to be (must be) overridden by derived classes. You could make it protected though if you like.
What am I missing here?
You have created operator which will get you class as a first argument and stream as the second.
my_square << std::cout;
I'd create free function and to make it dynamic I'd call some virtual method in it
I want to make a class based on "ostream" that does some auto-formatting to generate comma- or tab-separated-value files. My idea was to override "operator<<" to have it insert a separator before each value (except at the beginning and end of a line), and also to quote strings before writing them. Within the overriding "operator<<" method, I wanted to call the method of the base class, but I can't get it to work right.
Here's an example (compiles with g++ 4.3.3):
#include <iostream>
#include <ostream>
#include <string>
using namespace std;
class MyStream: public ostream
{
public:
MyStream(ostream& out): ostream(out.rdbuf()) {}
template <typename T> MyStream& operator<<(T value)
{
ostream::operator<<('+');
ostream::operator<<(value);
ostream::operator<<('+');
return *this;
}
};
template<> MyStream& MyStream::operator<< <string>(string value)
{
ostream::operator<<('*');
ostream::write(value.c_str(), value.size()); // ostream::operator<<(value);
ostream::operator<<('*');
return *this;
}
int main()
{
MyStream mystr(cout);
mystr << 10;
cout << endl;
mystr << "foo";
cout << endl;
mystr << string("test");
cout << endl;
return 0;
}
The two "operator<<" methods (template and specialization) are there to handle strings differently than everything else. But:
The characters ('+'/'*') are printed as numbers and not characters.
The C-String "foo" prints as a memory address (I think).
If the "write" line is exchanged with the commented part, the compiler complains that there's "no matching function for call to 'MyStream::operator<<(std::string&)'", even though I thought I was explicitly calling the base class method.
What am I doing wrong? Any help greatly appreciated.
The operator<< overloads that prints strings and characters are free functions. But as you force calling member functions, you will force them to convert to one candidate of the member functions declared in ostream. For '*', it will probably use the int overload, and for "foo", it will probably use the const void* overload.
I would not inherit ostream, but instead store the ostream as a reference member, and then delegate from your operator<< to it. I would also not make operator<< a member, but rather a free function template, and not specialize but overload the operator<< for both std::string and char const*.
Something like the following might work:
include
#include <ostream>
#include <string>
using namespace std;
class MyStream: public ostream
{
public:
MyStream(ostream& out): ostream(out.rdbuf()) {}
template <typename T> MyStream& operator<<(const T& value)
{
(ostream&)*this << '+' << value << '+';
return *this;
}
MyStream& operator<< (const string& value)
{
(ostream&)*this << '*' << value << '*';
return *this;
}
MyStream& operator<< (const char* cstr)
{
(ostream&)*this << '(' << cstr << ')';
return *this;
}
};
I overloaded operator <<
template <Typename T>
UIStream& operator<<(const T);
UIStream my_stream;
my_stream << 10 << " heads";
Works but:
my_stream << endl;
Gives compilation error:
error C2678: binary '<<' : no operator found which takes a left-hand operand of type 'UIStream' (or there is no acceptable conversion)
What is the work around for making my_stream << endl work?
std::endl is a function and std::cout utilizes it by implementing operator<< to take a function pointer with the same signature as std::endl.
In there, it calls the function, and forwards the return value.
Here is a code example:
#include <iostream>
struct MyStream
{
template <typename T>
MyStream& operator<<(const T& x)
{
std::cout << x;
return *this;
}
// function that takes a custom stream, and returns it
typedef MyStream& (*MyStreamManipulator)(MyStream&);
// take in a function with the custom signature
MyStream& operator<<(MyStreamManipulator manip)
{
// call the function, and return it's value
return manip(*this);
}
// define the custom endl for this stream.
// note how it matches the `MyStreamManipulator`
// function signature
static MyStream& endl(MyStream& stream)
{
// print a new line
std::cout << std::endl;
// do other stuff with the stream
// std::cout, for example, will flush the stream
stream << "Called MyStream::endl!" << std::endl;
return stream;
}
// this is the type of std::cout
typedef std::basic_ostream<char, std::char_traits<char> > CoutType;
// this is the function signature of std::endl
typedef CoutType& (*StandardEndLine)(CoutType&);
// define an operator<< to take in std::endl
MyStream& operator<<(StandardEndLine manip)
{
// call the function, but we cannot return it's value
manip(std::cout);
return *this;
}
};
int main(void)
{
MyStream stream;
stream << 10 << " faces.";
stream << MyStream::endl;
stream << std::endl;
return 0;
}
Hopefully this gives you a better idea of how these things work.
The problem is that std::endl is a function template, as your operator <<
is. So when you write:
my_stream << endl;
you'll like the compiler to deduce the template parameters for the operator
as well as for endl. This isn't possible.
So you have to write additional, non template, overloads of operator << to
work with manipulators. Their prototype will look like:
UIStream& operator<<(UIStream& os, std::ostream& (*pf)(std::ostream&));
(there are two others, replacing std::ostream by std::basic_ios<char> and
std::ios_base, which you have also to provide if you want to allow all
manipulators) and their implementation will be very similar to the one of
your templates. In fact, so similar that you can use your template for
implementation like this:
typedef std::ostream& (*ostream_manipulator)(std::ostream&);
UIStream& operator<<(UIStream& os, ostream_manipulator pf)
{
return operator<< <ostream_manipulator> (os, pf);
}
A final note, often writing a custom streambuf is often a better way to
achieve what one try to achieve applying to technique you are using.
I did this to solve my problem, here is part of my code:
template<typename T>
CFileLogger &operator <<(const T value)
{
(*this).logFile << value;
return *this;
}
CFileLogger &operator <<(std::ostream& (*os)(std::ostream&))
{
(*this).logFile << os;
return *this;
}
Main.cpp
int main(){
CFileLogger log();
log << "[WARNINGS] " << 10 << std::endl;
log << "[ERRORS] " << 2 << std::endl;
...
}
I got the reference in here http://www.cplusplus.com/forum/general/49590/
Hope this can help someone.
See here for better ways of extending IOStreams. (A bit outdated, and tailored for VC 6, so you will have to take it with a grain of salt)
The point is that to make functors work (and endl, which both outputs "\n" and flushes is a functor) you need to implement the full ostream interface.
The std streams are not designed to be subclassed as they have no virtual methods so I don't think you'll get too far with that. You can try aggregating a std::ostream to do the work though.
To make endl work you need to implement a version of operator<< that takes a pointer-to-function as that is how the manipulators such as endl are handled i.e.
UStream& operator<<( UStream&, UStream& (*f)( UStream& ) );
or
UStream& UStream::operator<<( UStream& (*f)( UStream& ) );
Now std::endl is a function that takes and returns a reference to a std::basic_ostream so that won't work directly with your stream so you'll need to make your own version which calls through to the std::endl version in your aggregated std::iostream.
Edit: Looks likes GMan's answer is better. He gets std::endl working too!
In addition to the accepted answer, with C++11 it is possible to overload operator<< for the type:
decltype(std::endl<char, std::char_traits<char>>)
Hey. Is it possible to overload operator<< for primitive types? Fx lets say that I want to write a std::endl each time want to write a int. Can I overload operator<< for int, so that it automatic puts a std::endl to the output? I have tried with this,
std::ostream& operator<<(std::ostream& strm, int & i)
{
strm << i << std::endl;
return strm;
}
but it doesn't work. I cant recall the compiler error message, but I think that I'm getting operator overloading all wrong any ways.
I try to call the above overloaded operator<< in this way,
int main()
{
int i = 2;
std::out<<"Here is an int " << i;
return 0;
}
But it doesn't work at all. Maybe I can't overload POD types?
As zabzonk said, the standard library provides an (ostream&, int) overload so you can't define another.
To simulate what you were doing (though it is completely pointless in its present form :) :
class EndlinedInteger {
public:
EndlinedInteger(int i) : i(i) { }
friend ostream& operator<<(ostream&, EndlinedInteger const&);
private:
int i;
};
ostream& operator<<(ostream& out, EndlinedInteger const& ei) {
out << ei.i << endl;
return out;
}
int main()
{
EndlinedInteger i = 2;
std::cout<<"Here is an int " << i;
}
Remember that here you use << operator not only on int but also on ostream. You could derive from ostream and implement it in your own derived class, but I would suggest to make a simple macro like
#define EL(i) (i)<<std::endl
Alternatively you could make boxed int class and override the << for standard ostream and boxed int (like in answer by Iraimbilanja) class. Sounds like huge overkill but could work.
Your problem is that there is already an overload for operator << (ostream &, int), the one supplied by the C++ standard library. If you remove the overload definition and use:
#include <iostream>
int main()
{
int i = 2;
std::out<<"Here is an int " << i;
return 0;
}
things work as expected.
And BTW, compiler error messages are kind of important, so it's a good idea to remember them and quote them in posts when asking questions.
edit - std::out above should of couse be std::cout