473,399 Members | 4,192 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,399 software developers and data experts.

Can I overload operator<< using a template?

I have some classes which have a "writeTo()" function
but no operator<<. I want to fix it so that they
all have an operator<< (for consistency).

Can I do something like this:

template <class T>
DataDest& operator<<(DataDest& d, const T& t)
{
t.writeTo(d);
return d;
}

I tried the above but I get errors like "no operator
found which takes a right-hand operand of type XXX".

Do I need to write all the operator<< and operator>>
functions by hand?

Also, a peeve: Why can't the compiler write operator==
and operator< for me automatically? I have some structs
with about 50 members in them (mostly float values) and
to write/maintain operator==/operator< functions for
them is a pain (not to mention bug-prone).

I'm sure the compiler could do this for me automatically
in exactly the same way that it generates operator= and
copy constructors.

Is there a good reason why this wasn't done? Something
I'm missing...?
--
<\___/>
/ O O \
\_____/ FTB. For email, remove my socks.
We’re judging how a candidate will handle a nuclear
crisis by how well his staff creates campaign ads.
It’s a completely nonsensical process.
Jan 5 '07 #1
11 3527

fungus napsal:
I have some classes which have a "writeTo()" function
but no operator<<. I want to fix it so that they
all have an operator<< (for consistency).

Can I do something like this:

template <class T>
DataDest& operator<<(DataDest& d, const T& t)
{
t.writeTo(d);
return d;
}

I tried the above but I get errors like "no operator
found which takes a right-hand operand of type XXX".

Do I need to write all the operator<< and operator>>
functions by hand?
It should work with template:

#include <iostream>
#include <string>

class A
{
public:
A(int data1 = 0, int data2 = 0)
: data1_(data1),
data2_(data2)
{
}

void writeTo(std::ostream& os) const
{
os << '[' << data1_ << ';' << data2_ << ']';
}

private:
int data1_;
int data2_;
};

template<typename T, typename S>
S& operator<<(S& d, const T& t)
{
t.writeTo(d);
return d;
}

int main(int argc,char **argv)
{
A a1(3, 5);
A a2(-1, 12);
std::string some_text(" <--");

std::cout << a1 << some_text << a2 << '\n';
}
Also, a peeve: Why can't the compiler write operator==
and operator< for me automatically? I have some structs
with about 50 members in them (mostly float values) and
to write/maintain operator==/operator< functions for
them is a pain (not to mention bug-prone).

I'm sure the compiler could do this for me automatically
in exactly the same way that it generates operator= and
copy constructors.
Well, it could do it, but it does not. it is designed this way, so take
it as it is.

Jan 5 '07 #2
fungus wrote:
I have some classes which have a "writeTo()" function
but no operator<<. I want to fix it so that they
all have an operator<< (for consistency).

Can I do something like this:

template <class T>
DataDest& operator<<(DataDest& d, const T& t)
{
t.writeTo(d);
return d;
}

I tried the above but I get errors like "no operator
found which takes a right-hand operand of type XXX".
That should work. Your code is a bit short, so it's hard to tell why it
wouldn't. It's better to show a minimal, but complete program that exhibits
the observed behavior. The following program does compile without error
here:

class DataDest
{
};

class MyClass
{
public:
void writeTo(DataDest& d) const {}
};

template <class T>
DataDest& operator<<(DataDest& d, const T& t)
{
t.writeTo(d);
return d;
}

int main()
{
MyClass x;
DataDest d;
d << x;
}
Do I need to write all the operator<< and operator>>
functions by hand?
The template should be fine.
Also, a peeve: Why can't the compiler write operator==
and operator< for me automatically? I have some structs
with about 50 members in them (mostly float values) and
to write/maintain operator==/operator< functions for
them is a pain (not to mention bug-prone).

I'm sure the compiler could do this for me automatically
in exactly the same way that it generates operator= and
copy constructors.

Is there a good reason why this wasn't done? Something
I'm missing...?
I think that's more of a question for comp.std.c++. That newsgroup deals
more with the why than the how. Here, we just accept the C++ language as it
is. ;-)

Jan 5 '07 #3

fungus wrote:
Also, a peeve: Why can't the compiler write operator==
and operator< for me automatically? I have some structs
with about 50 members in them (mostly float values) and
to write/maintain operator==/operator< functions for
them is a pain (not to mention bug-prone).
Yep, that is a common problem with large, primitive obsessed objects.
You need to rethink your design here and group your data better.

If you want a language that will make your design mistakes easier to
work with you've come to the wrong place. Luckily this one isn't too
hard to fix though if you have a bunch of places where this data is
accessed directly you're going to be there for a while.

Jan 5 '07 #4
Noah Roberts wrote:
fungus wrote:
Also, a peeve: Why can't the compiler write operator==
and operator< for me automatically? I have some structs
with about 50 members in them (mostly float values) and
to write/maintain operator==/operator< functions for
them is a pain (not to mention bug-prone).

Yep, that is a common problem with large, primitive obsessed objects.
You need to rethink your design here and group your data better.
Besides, what is the compiler supposed to do with pointer members?
Should it compare values or pointed-to-addresses? If values, what
should it do if one or both pointers is null? What if a pointer is
simply uninitialized? (Answer: you've got a very subtle, hard-to-find
bug on your hands because it's hidden in implicit code.)

Cheers! --M

Jan 5 '07 #5
Also, a peeve: Why can't the compiler write operator==
and operator< for me automatically? I have some structs
with about 50 members in them (mostly float values) and
to write/maintain operator==/operator< functions for
them is a pain (not to mention bug-prone).

I'm sure the compiler could do this for me automatically
in exactly the same way that it generates operator= and
copy constructors.

Is there a good reason why this wasn't done? Something
I'm missing...?
Concerning operator<:

struct foo {
std::string employee_name;
Date date_hired;
// ...
};

foo employers[2]=//...

if(employers[0]>employers[1]) {
// how does the compiler know whether to
// compare by employee_name or by date_hired?
}

HTH,
- J.
Jan 5 '07 #6
mlimber wrote:
Noah Roberts wrote:
>fungus wrote:
Also, a peeve: Why can't the compiler write operator==
and operator< for me automatically? I have some structs
with about 50 members in them (mostly float values) and
to write/maintain operator==/operator< functions for
them is a pain (not to mention bug-prone).
I can see that it could be useful to have an auto-generated operator==, but
how would the compiler generate operator<? When is an object 'less' than
another? If all members are 'less'? If one member is 'less'? Which one
then? Or should it do a lexographical comparison? Which order should it use
in that case?
>Yep, that is a common problem with large, primitive obsessed objects.
You need to rethink your design here and group your data better.

Besides, what is the compiler supposed to do with pointer members?
Should it compare values or pointed-to-addresses?
It should compare the member's value, and since the member is a pointer,
that means the address. The language should never implicitly dereference a
pointer.
If values, what should it do if one or both pointers is null? What if a
pointer is simply uninitialized? (Answer: you've got a very subtle,
hard-to-find bug on your hands because it's hidden in implicit code.)
How does that differ from the assignment operator, which is
compiler-generated by default?

Jan 5 '07 #7
Rolf Magnus wrote:
That should work. Your code is a bit short, so it's hard to tell why it
wouldn't.
I'll have another play with it and see what happens
It's better to show a minimal, but complete program that exhibits
the observed behavior.
- but the code is so simple...(!)

Yep, that is a common problem with large, primitive obsessed objects.
You need to rethink your design here and group your data better.

If you want a language that will make your design mistakes easier to
work with you've come to the wrong place.
I have a class which represents a "material".
Materials have a lot of properties, there's no
way around that. I want to put materials in a
std::map for lookup so I need an operator<. I
need to compare two materials so I need an
operator=.

I don't see how there's a "design flaw" here.
--
<\___/>
/ O O \
\_____/ FTB. For email, remove my socks.
We’re judging how a candidate will handle a nuclear
crisis by how well his staff creates campaign ads.
It’s a completely nonsensical process.
Jan 6 '07 #8
mlimber wrote:
fungus wrote:
>>
Why can't the compiler write operator==
and operator< for me automatically?

what is the compiler supposed to do with pointer members?
Should it compare values or pointed-to-addresses? If values, what
should it do if one or both pointers is null? What if a pointer is
simply uninitialized?
You have exactly the same problem with assignment
operator and copy constructor but the compiler
seems happy enough to do those for me.

--
<\___/>
/ O O \
\_____/ FTB. For email, remove my socks.
We’re judging how a candidate will handle a nuclear
crisis by how well his staff creates campaign ads.
It’s a completely nonsensical process.
Jan 6 '07 #9
Rolf Magnus wrote:
fungus wrote:
>Why can't the compiler write operator==
and operator< for me automatically?
how would the compiler generate operator<?
The code I'm writing at the moment looks like this:
struct item {
float value1;
float value2;
...
};

bool operator<(const item& a, const item& b)
{
// value1
if (a.value1 < b.value1) return true;
if (b.value1 < a.value1) return false;

// value2
if (a.value2 < b.value2) return true;
if (b.value2 < a.value2) return false;

// ...

// If we reach here then a and b are equal
return false;
}
--
<\___/>
/ O O \
\_____/ FTB. For email, remove my socks.
We’re judging how a candidate will handle a nuclear
crisis by how well his staff creates campaign ads.
It’s a completely nonsensical process.
Jan 6 '07 #10
Jacek Dziedzic wrote:
fungus wrote:
>Why can't the compiler write operator==
and operator< for me automatically?

// how does the compiler know whether to
// compare by employee_name or by date_hired?
If I want specifics like these then I'll write
appropriate code but I can think of many
situations where all I want is generic compares
and fast lookups (eg. std::map, std::lower_bound).
--
<\___/>
/ O O \
\_____/ FTB. For email, remove my socks.
We’re judging how a candidate will handle a nuclear
crisis by how well his staff creates campaign ads.
It’s a completely nonsensical process.
Jan 6 '07 #11
fungus wrote:
Rolf Magnus wrote:
>That should work. Your code is a bit short, so it's
hard to tell why it wouldn't.

I'll have another play with it and see what happens...
I figured it out - it's all to do with namespaces.

Here's a "broken" piece of code:

#include <iostream>
#include <string>

namespace foo {
class A {
public:
void writeTo(std::ostream& os) const {
os << "A";
}
};
void operator<<(std::ostream& os, const class B&);
void test();
}

template<typename T, typename S>
S& operator<<(S& d, const T& t)
{
t.writeTo(d);
return d;
}

void foo::test()
{
A a;
std::cout << a << '\n';
}

int main(int argc,char **argv)
{
foo::test();
}
The operator<< in namespace foo is hiding the template
operator<< (which is in the global namespace).
--
<\___/>
/ O O \
\_____/ FTB. For email, remove my socks.
We’re judging how a candidate will handle a nuclear
crisis by how well his staff creates campaign ads.
It’s a completely nonsensical process.
Jan 6 '07 #12

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
by: Guenther Brunthaler | last post by:
Hi template specialists, I have a problem with the code listed below. What I wanted to do is defining an operator<< that is able to output a 'matrix<ELEMENT_T, INDEX_T>::subrange' object into...
4
by: Shailesh | last post by:
Hi! I want to overload << operator so that it can print an arry defined in MyClass.My problem is that I want to print only a no of elements NOT all the elements in the array and this no of...
5
by: Eric Lilja | last post by:
Ok, this code doesn't compile: #include <iostream> #include <ostream> /* Just for you, Mike :-) */ template<typename T> class Couple { public: Couple(const T& ax, const T& ay) : x(ax), y(ay)...
4
by: bart.kowalski | last post by:
Hello, I'm trying to overload operator << for class CString, which has an operator const char *. I thought the following code would do: template <typename T> inline std::basic_ostream<T>...
14
by: lutorm | last post by:
Hi everyone, I'm trying to use istream_iterators to read a file consisting of pairs of numbers. To do this, I wrote the following: #include <fstream> #include <vector> #include <iterator> ...
4
by: bluekite2000 | last post by:
Here A is an instantiation of class Matrix. This means whenever user writes Matrix<float> A=rand<float>(3,2);//create a float matrix of size 3x2 //and fills it up w/ random value cout<<A; the...
4
by: CrimzonRJ | last post by:
Theoretically, how are you supposed to overload << as friend to a template class? I keep getting an 'unresolved extern symbol' error. Is this even a smart thing to do?
1
by: Sunny | last post by:
The way to overload operator << is : ostream& operator << (ostream& os, const Obj& obj); and this is a member function. My question is why do we need to provide a const reference of Obj as...
10
by: ozizus | last post by:
I overloaded operator << for STL map successfully: template <typename T1, typename T2ostream & operator << (ostream & o, map <T1,T2& m) { //code } the code works like a charm. Now, I want...
2
by: soy.hohe | last post by:
Hi all I have a class StreamLogger which implements operator << in this way: template <class TStreamLogger& operator<<(const T& t) { <print the stuff using fstream, etc.> return *this; }
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.