Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c++ > #5152 > unrolled thread

Re: ::std::ostream << char

Started by"Alf P. Steinbach /Usenet" <alf.p.steinbach+usenet@gmail.com>
First post2011-05-19 01:39 +0200
Last post2011-05-19 18:11 -0400
Articles 3 — 3 participants

Back to article view | Back to comp.lang.c++

This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by below is the oldest one visible, not the original post.


Contents

  Re: ::std::ostream << char "Alf P. Steinbach /Usenet" <alf.p.steinbach+usenet@gmail.com> - 2011-05-19 01:39 +0200
    Re: ::std::ostream << char Björn <hen03@nurfuerspam.de> - 2011-05-19 23:27 +0200
      Re: ::std::ostream << char Pete Becker <pete@versatilecoding.com> - 2011-05-19 18:11 -0400

#5152 — Re: ::std::ostream << char

From"Alf P. Steinbach /Usenet" <alf.p.steinbach+usenet@gmail.com>
Date2011-05-19 01:39 +0200
SubjectRe: ::std::ostream << char
Message-ID<ir1l04$h6k$1@dont-email.me>
* Stefan Ram, on 19.05.2011 00:54:
> The output operator "<<" for operands of type »::std::ostream« and »char« (in
> this order) seems to be defined as a non-member, while for »double« it seems
> to be defined as a member.

This may depend on which standard you're talking about. I haven't checked but as
I recall some of the issues related to this were fixed in C++0x. Which is on its 
way Real Soon Now.


> Why is this so?

Historical accident.


> Bjarne Stroustrup already explained some of this: He said that "<<" /can/ be
> defined as a non-member, because the class already has the member »put«, so
> it can be defined outside of the class using »put«. But why do we /prefer/
> this?

We don't. Perhaps some do. It depends on what functionality you desire:

   * Member (of LHS type), can be called on temporary.

   * Non-member (of LHS type), can be invoked on object that just provides
     conversion to the relevant formal argument type.

To me, the possibility of calling << with a left hand side operand that just
provides a conversion to referece to the relevant stream type, is completely 
irrelevant.



> Herb Sutter explained, why "<<" for his class »Complex« has to be defined as
> a non-member of this class »Complex«, but his reason does not apply to the
> class »::std::ostream« as far as I understand it.

Now you're talking about the right hand side operand type.

That's a different thing.

An expression like "a << b" makes sense as "a.operator<<( b )" if the operator
is a member of typeof(a), but not if it is a member of typeof(b).


> Sometimes people say: When you define the operators as non-members and the
> class has implicit conversion operators, those implicit conversions will
> behave more symmetric with respect to the two operands of a binary operator,
> when this operator is defined as a non-member. I can not understand all of
> this, because I lack some prerequisites, but I have a vague idea of what it
> might mean. Does this reason apply to »::std::ostream« and "<<
> static_cast<char>(...)"?

In practice such conversions do not intrude very much.

However, when you define a symmetric operator like +, then it doesn't make much 
sense to single out the left hand argument as special.

So then it might feel much more natural to define a non-member function.


> Could someone give a specific example of a case where something would be
> worse when "<<  static_cast<char>(...)" would have been defined as a member
> of ::std::ostream?

Define "worse".


> Or, an example of a case where something would be worse when "<<
> static_cast<double>(...)" would have been defined as a non-member of
> ::std::ostream?
>
> (This question is inspired by a similar question posted into the German
> language C++ newsgroup by someone else recently.)

Oh, them Germans.


Cheers & hth.,

- Alf

-- 
blog at <url: http://alfps.wordpress.com>

[toc] | [next] | [standalone]


#5187

FromBjörn <hen03@nurfuerspam.de>
Date2011-05-19 23:27 +0200
Message-ID<ir420o$6kt$1@online.de>
In reply to#5152
Alf P. Steinbach /Usenet wrote:

> * Stefan Ram, on 19.05.2011 00:54:
>> The output operator "<<" for operands of type »::std::ostream« and
>> »char« (in this order) seems to be defined as a non-member, while
>> for »double« it seems to be defined as a member.
> 
> This may depend on which standard you're talking about. I haven't
> checked but as I recall some of the issues related to this were
> fixed in C++0x. Which is on its way Real Soon Now.

In the current draft N3242 from 2011-02-28 it is still as described.

>> Bjarne Stroustrup already explained some of this: He said that "<<"
>> /can/ be defined as a non-member, because the class already has the
>> member »put«, so it can be defined outside of the class using
>> »put«. But why do we /prefer/ this?
> 
> We don't. Perhaps some do. It depends on what functionality you
> desire:
> 
>    * Member (of LHS type), can be called on temporary.
> 
>    * Non-member (of LHS type), can be invoked on object that just
>    provides
>      conversion to the relevant formal argument type.
> 
> To me, the possibility of calling << with a left hand side operand
> that just provides a conversion to referece to the relevant stream
> type, is completely irrelevant.

I agree. I cannot imagine any reason to define an output stream class 
which is not derived from std::basic_ostream but on the other hand 
every library and particularly the STL should be as flexible as 
possible.

I found at least a reason why some operator<< are members of 
std::basic_ostream. They all have operands which will be converted to 
several characters usually (numbers, pointers, and another stream 
buffer). So, for an implementation it will probably be more efficient 
if they insert the produced characters directly into the output buffer 
-- if available -- than passing a temporary buffer to 
std::basic_ostream::write.

The remaining operator<< in <ostream> only insert single characters.

Another operator<< is in <string> to insert std::basic_string. But in 
case of a string you have to copy a character sequence into the output 
buffer, anyway, so it doesn't hurt that it's not a member function.

I haven't checked if there are more operator<< in the STL.

> However, when you define a symmetric operator like +, then it
> doesn't make much sense to single out the left hand argument as
> special.
> 
> So then it might feel much more natural to define a non-member
> function.

For me it feels more natural to define everything inside according to 
the rule "as local as possible".

>> (This question is inspired by a similar question posted into the
>> German language C++ newsgroup by someone else recently.)
> 
> Oh, them Germans.

BTW, I'm the one who came up with the topic. I asked about 
std::basic_istream as well but the answer will probably be the same, 
so, it's easier to talk only about std::basic_ostream.

Björn

[toc] | [prev] | [next] | [standalone]


#5189

FromPete Becker <pete@versatilecoding.com>
Date2011-05-19 18:11 -0400
Message-ID<201105191811177950-pete@versatilecodingcom>
In reply to#5187
On 2011-05-19 17:27:52 -0400, Björn said:

> Alf P. Steinbach /Usenet wrote:
> 
>> * Stefan Ram, on 19.05.2011 00:54:
>>> The output operator "<<" for operands of type »::std::ostream« and
>>> »char« (in this order) seems to be defined as a non-member, while
>>> for »double« it seems to be defined as a member.
>> 
>> This may depend on which standard you're talking about. I haven't
>> checked but as I recall some of the issues related to this were
>> fixed in C++0x. Which is on its way Real Soon Now.
> 
> In the current draft N3242 from 2011-02-28 it is still as described.

Yes, that hasn't been changed.

-- 
  Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of "The 
Standard C++ Library Extensions: a Tutorial and Reference 
(www.petebecker.com/tr1book)

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.c++


csiph-web