473,320 Members | 2,147 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,320 software developers and data experts.

Template specialization of an operator

Hi, I am having a bit of trouble with a specialization of operator<<.
Here goes:

class MyStream
{
};
template <typename T>
MyStream& operator<<(MyStream& lhs, T const &)
{
cout << "operator<< T" << endl;
return lhs;
}

// specialize to work differently for std::string
template <> MyStream& operator<<(MyStream& lhs, string const &)
{
cout << "operator<< const string&" << endl;
return lhs;
}

// specialize to work differently for char const*
template <> MyStream& operator<<(MyStream& lhs, char const * const &)
{
cout << "operator<< char const*" << endl;
return lhs;
}

int main()
{
MyStream strm;
int i = 19;
string mystr = "hello";
strm << "hi" << i << mystr << "\n";
return 0;
}

This outputs:
operator<< T
operator<< T
operator<< const string&
operator<< T

Why doesn't strm << "hi" (and << "\n") use the specialized version?
Now I tried changing the operator to these:

template <typename T>
MyStream& operator<<(MyStream& lhs, T)
{
cout << "operator<< T" << endl;
return lhs;
}

// specialize to work differently for std::string
template <> MyStream& operator<<(MyStream& lhs, string const &)
{
cout << "operator<< const string&" << endl;
return lhs;
}

// specialize to work differently for char const*
template <> MyStream& operator<<(MyStream& lhs, char const *)
{
cout << "operator<< char const*" << endl;
return lhs;
}

And the output is:
operator<< char const*
operator<< char const*
operator<< T
operator<< char const*

Now why doesn't strm << mystr use the specialized one? It looks like
it's a perfect match for mystr (not even using a specialization for
string& works).

Can anyone tell me why this happens, and if there is a way to make this
work for both char const* and string const& ?

Thanks a lot,
George Faraj

Jul 31 '05 #1
6 4374
YUY0x7 wrote:
Hi, I am having a bit of trouble with a specialization of operator<<.
Here goes:

class MyStream
{
};
template <typename T>
MyStream& operator<<(MyStream& lhs, T const &)
{
cout << "operator<< T" << endl;
return lhs;
}

// specialize to work differently for std::string
template <> MyStream& operator<<(MyStream& lhs, string const &)
{
cout << "operator<< const string&" << endl;
return lhs;
}

// specialize to work differently for char const*
template <> MyStream& operator<<(MyStream& lhs, char const * const &)
{
cout << "operator<< char const*" << endl;
return lhs;
}

int main()
{
MyStream strm;
int i = 19;
string mystr = "hello";
strm << "hi" << i << mystr << "\n";
return 0;
}

This outputs:
operator<< T
operator<< T
operator<< const string&
operator<< T

Why doesn't strm << "hi" (and << "\n") use the specialized version?
Now I tried changing the operator to these:

template <typename T>
MyStream& operator<<(MyStream& lhs, T)
{
cout << "operator<< T" << endl;
return lhs;
}

// specialize to work differently for std::string
template <> MyStream& operator<<(MyStream& lhs, string const &)
{
cout << "operator<< const string&" << endl;
return lhs;
}

// specialize to work differently for char const*
template <> MyStream& operator<<(MyStream& lhs, char const *)
{
cout << "operator<< char const*" << endl;
return lhs;
}

And the output is:
operator<< char const*
operator<< char const*
operator<< T
operator<< char const*

Now why doesn't strm << mystr use the specialized one? It looks like
it's a perfect match for mystr (not even using a specialization for
string& works).

Can anyone tell me why this happens, and if there is a way to make this
work for both char const* and string const& ?

Thanks a lot,
George Faraj


The following mods to your program produces:

operator<< char const*
operator<< T
operator<< const string&
operator<< char const*

Note the changes to the placement of the 'const' keyword
in the various templates and the addition of a template for
pointer args.

// ----------------------
#include <iostream>
#include <string>

using namespace std;

class MyStream
{
};

// default operator<<() for 'const T&' arg
template <typename T>
MyStream& operator<<(MyStream& lhs, const T&)
{
cout << "operator<< T" << endl;
return lhs;
}

// default operator<<() for 'const T *' arg
template <typename T>
MyStream& operator<<(MyStream& lhs, const T *)
{
cout << "operator<< T" << endl;
return lhs;
}

// specialize to work differently for 'const string&'
template <> MyStream& operator<<(MyStream& lhs, const string&)
{
cout << "operator<< const string&" << endl;
return lhs;
}

// specialize to work differently for 'const char *'
template <> MyStream& operator<<(MyStream& lhs, const char *)
{
cout << "operator<< char const*" << endl;
return lhs;
}

int main()
{
MyStream strm;
int i = 19;
string mystr = "hello";
strm << "hi" << i << mystr << "\n";
return 0;
}

Regards,
Larry
Jul 31 '05 #2
Ah, interesting. That helps a lot, thank you very much...

Jul 31 '05 #3

YUY0x7 wrote:
Hi, I am having a bit of trouble with a specialization of operator<<.
Here goes:

class MyStream
{
};
template <typename T>
MyStream& operator<<(MyStream& lhs, T const &)
{
cout << "operator<< T" << endl;
return lhs;
}

// specialize to work differently for std::string
template <> MyStream& operator<<(MyStream& lhs, string const &)
{
cout << "operator<< const string&" << endl;
return lhs;
}

// specialize to work differently for char const*
template <> MyStream& operator<<(MyStream& lhs, char const * const &)
{
cout << "operator<< char const*" << endl;
return lhs;
}

int main()
{
MyStream strm;
int i = 19;
string mystr = "hello";
strm << "hi" << i << mystr << "\n";
return 0;
}

This outputs:
operator<< T
operator<< T
operator<< const string&
operator<< T

Why doesn't strm << "hi" (and << "\n") use the specialized version?
Now I tried changing the operator to these:

template <typename T>
MyStream& operator<<(MyStream& lhs, T)
{
cout << "operator<< T" << endl;
return lhs;
}

// specialize to work differently for std::string
template <> MyStream& operator<<(MyStream& lhs, string const &)
{
cout << "operator<< const string&" << endl;
return lhs;
}

// specialize to work differently for char const*
template <> MyStream& operator<<(MyStream& lhs, char const *)
{
cout << "operator<< char const*" << endl;
return lhs;
}

And the output is:
operator<< char const*
operator<< char const*
operator<< T
operator<< char const*

Now why doesn't strm << mystr use the specialized one? It looks like
it's a perfect match for mystr (not even using a specialization for
string& works).

Can anyone tell me why this happens, and if there is a way to make this
work for both char const* and string const& ?


String literals have type char const[]. To fix the code you may want to
replace your char const* overload with this one:

template <unsigned n>
MyStream& operator<<(MyStream& lhs, char const(&arr)[n])
{
cout << "operator<< char const*" << endl;
return lhs;
}

Jul 31 '05 #4
* YUY0x7:

class MyStream
{
};
template <typename T>
MyStream& operator<<(MyStream& lhs, T const &)
{
cout << "operator<< T" << endl;
return lhs;
}

// specialize to work differently for std::string
template <> MyStream& operator<<(MyStream& lhs, string const &)
{
cout << "operator<< const string&" << endl;
return lhs;
}

// specialize to work differently for char const*
template <> MyStream& operator<<(MyStream& lhs, char const * const &)
{
cout << "operator<< char const*" << endl;
return lhs;
}

int main()
{
MyStream strm;
int i = 19;
string mystr = "hello";
strm << "hi" << i << mystr << "\n";
return 0;
}

This outputs:
operator<< T
operator<< T
operator<< const string&
operator<< T

Why doesn't strm << "hi" (and << "\n") use the specialized version?
First off, Larry Smith's comment about placement of 'const', that you should
"note" it, is misleading:

the placement of 'const' has nothing to do with it.

As Maxim Yegorushkin wrote, a character literal has type 'char const[N]',
which means that while the generic template matches exactly, your 'char
const*' version requires a type conversion, namely decay to pointer. The
compiler chooses the exact match in preference to the conversion. Also as
Maxim wrote you can fix your code by introducing an array argument template,
which I'd do as follows, reusing the existing code (no changes to it):

template< size_t size >
MyStream& operator<<(MyStream& lhs, char const (&s)[size] )
{
return operator<<( lhs, &s[0] );
}

Your 'char const*' function kicks in when you supply an actual pointer as
argument.

The forwarder above kicks in when you supply a character array as argument,
such as a character string literal.

Now I tried changing the operator to these:

template <typename T>
MyStream& operator<<(MyStream& lhs, T)
{
cout << "operator<< T" << endl;
return lhs;
}

// specialize to work differently for std::string
template <> MyStream& operator<<(MyStream& lhs, string const &)
{
cout << "operator<< const string&" << endl;
return lhs;
}

// specialize to work differently for char const*
template <> MyStream& operator<<(MyStream& lhs, char const *)
{
cout << "operator<< char const*" << endl;
return lhs;
}

And the output is:
operator<< char const*
operator<< char const*
operator<< T
operator<< char const*

Now why doesn't strm << mystr use the specialized one? It looks like
it's a perfect match for mystr (not even using a specialization for
string& works).
This one is more difficult and I'm not sure of the answer. I hadn't viewed
a conversion to reference as a type conversion, but perhaps that's what's
needed to understand this: to view string -> string& as a type conversion.
A counter argument is that the actual function call arg is already of type
string& because it's an lvalue, not (only) an rvalue.

Anyway, the string -> string& as conversion view "works" wrt. to the various
outcomes when removing the & for the string specialization, and when adding
a const& for the generic version.

Someone better versed in the details of the standard regarding this issue
can probably explain why string -> string& apparently counts as conversion
in this case (I could probably do it by taking the time, but, enough! ;-)).

Can anyone tell me why this happens,
See above.

and if there is a way to make this
work for both char const* and string const& ?


See above.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Jul 31 '05 #5
Thanks Maxim and Alf...
First off, Larry Smith's comment about placement of 'const', that you should
"note" it, is misleading:


Hah, I didn't even notice that comment made by Larry. I know that the
placement of 'const' had nothing to do with it. I always like to put it
on the left because it makes it clearer what the 'const' is modifying.

Anyways, Larry's solution worked, but the one proposed later by Maxim
and Alf looks more appropriate (shorter too).

Thanks to you three for responding.

Aug 1 '05 #6
Damn... I put 'const' on the right, sorry.

Aug 1 '05 #7

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

Similar topics

2
by: Elven | last post by:
Hi! I was trying to find the solution to this problem, but I don't think I could quite come up with the correct keywords to find it, since I'm pretty sure it's been asked before. In short,...
6
by: Ben Ingram | last post by:
Hi all, I am writing a template matrix class in which the template parameters are the number of rows and number of columns. There are a number of reasons why this is an appropriate tradeoff for...
5
by: Senthilvel | last post by:
Hi , I am trying out a few templates and i got stuck in template specialization. The normal template Add(just like a plus of the fubnctional) works fine. But i wanted to specialize it for a map so...
6
by: Gonçalo Rodrigues | last post by:
Hi all, The following (test) program is not working as I expected. Note: The code is a bit long but is easy to understand: There is a class Object implementing ref counting. A Ref<T> template...
5
by: __PPS__ | last post by:
Hello, I want to write specialized method for a class: template<class A, class B> class xxx{ A a; B b; operator bool()const{ a==b; } };
6
by: merdem | last post by:
Hi all, I just started to mess around with templates. First I declared a class Image as follows(this is a small version of the real thing which is pretty big): template<int depth, int space,...
8
by: mattias.nissler | last post by:
Hi! Here is a problem I ran into at work. The following example doesn't compile on gcc-4.1: struct cons_end {}; template<typename U,typename Vstruct cons { U elem; V tail;
7
by: aaragon | last post by:
Hi everyone, The idea is quite simple: generate a container with random values in it. For that, I decided to create a class that I called RandomContainer that inherits from a container (with...
2
by: Barry | last post by:
The following code compiles with VC8 but fails to compiles with Comeau online, I locate the standard here: An explicit specialization of any of the following:
0
by: DolphinDB | last post by:
The formulas of 101 quantitative trading alphas used by WorldQuant were presented in the paper 101 Formulaic Alphas. However, some formulas are complex, leading to challenges in calculation. Take...
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
1
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: Vimpel783 | last post by:
Hello! Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
0
by: jfyes | last post by:
As a hardware engineer, after seeing that CEIWEI recently released a new tool for Modbus RTU Over TCP/UDP filtering and monitoring, I actively went to its official website to take a look. It turned...
0
by: ArrayDB | last post by:
The error message I've encountered is; ERROR:root:Error generating model response: exception: access violation writing 0x0000000000005140, which seems to be indicative of an access violation...
0
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
by: Defcon1945 | last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work
0
by: Shællîpôpï 09 | last post by:
If u are using a keypad phone, how do u turn on JavaScript, to access features like WhatsApp, Facebook, Instagram....

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.