Topic: inserters and extractors virtual?


Author: James Kanze <james-albert.kanze@vx.cit.alcatel.fr>
Date: 1997/03/05
Raw View
kuehl@uzwil.informatik.uni-konstanz.de (Dietmar Kuehl) writes:

|>  Steve Clamage (Stephen.Clamage@Eng.Sun.COM) wrote:
|>  : Interestingly, the argument *against* making them virtual is the same.
|>  : Suppose I write an extractor for MyClass:
|>  :  ostream& operator<<(ostream& o, const MyClass& m) {
|>  :   o << '[' << m.data1 << '\t' << m.data2 << ']';
|>  :   return o;
|>  :  }
|>  : Because inserters are not virtual, I know exactly what the output format
|>  : will look like, and in particular I know that any extractor I write can
|>  : can depend on reading that format. If inserters were virtual, I could not
|>  : depend on the output format, nor write an extractor that would be sure to
|>  : work.
|>
|>  This argument cannot hold! It is impossible to predict exactly what the
|>  output format will look like since it depends on the 'locale' currently
|>  being used. I posted yesterday an article to comp.lang.c++.moderated
|>  describing a style how to modify the output behavior for 'double' using
|>  a modified 'num_put' 'facet'. The intentation was to provide something
|>  like the "Fortran 77 G edit dscriptor" (I don't know what this is
|>  exactly but I know how to implement the framework for doing this...).
|>  Of course, this can be seen as an abuse of locales but at least it
|>  works.

This is definitly an abuse of locales.  Offhand, of course, I don't see
anyway the standard could prevent it, and of course, the goal is to
protect against Murphy, not Machiavelli.  I think that we would all
agree that this is not the designed purpose of locale, and that during
the design of locale, no effort was made to support this use.

Steve's point was, of course, that overriding operator<< and operator>>
would be an abuse of [io]stream as well.  Thus, during the design of
[io]stream, no effort was made to support this use.  Since this use
would require a special effort (declaring the operators virtual), the
standard effectively prevents it.  I suspect, however, that it is more a
question that no effort was made to support it, rather than an
intentional effort made to thwart the Machiavellis who want to abuse
iostream.

--
James Kanze      home:     kanze@gabi-soft.fr        +33 (0)1 39 55 85 62
                 office:   kanze@vx.cit.alcatel.fr   +33 (0)1 69 63 14 54
GABI Software, Sarl., 22 rue Jacques-Lemercier, F-78000 Versailles France
     -- Conseils en informatique industrielle --
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: kuehl@uzwil.informatik.uni-konstanz.de (Dietmar Kuehl)
Date: 1997/03/06
Raw View
Hi,
James Kanze (james-albert.kanze@vx.cit.alcatel.fr) wrote:
: kuehl@uzwil.informatik.uni-konstanz.de (Dietmar Kuehl) writes:

: |>  Steve Clamage (Stephen.Clamage@Eng.Sun.COM) wrote:
: |>  : Interestingly, the argument *against* making them virtual is the same.
: |>  : Suppose I write an extractor for MyClass:
: |>  :  ostream& operator<<(ostream& o, const MyClass& m) {
: |>  :   o << '[' << m.data1 << '\t' << m.data2 << ']';
: |>  :   return o;
: |>  :  }
: |>  : Because inserters are not virtual, I know exactly what the output format
: |>  : will look like, and in particular I know that any extractor I write can
: |>  : can depend on reading that format. If inserters were virtual, I could not
: |>  : depend on the output format, nor write an extractor that would be sure to
: |>  : work.
: |>
: |>  This argument cannot hold! It is impossible to predict exactly what the
: |>  output format will look like since it depends on the 'locale' currently
: |>  being used. I posted yesterday an article to comp.lang.c++.moderated
: |>  describing a style how to modify the output behavior for 'double' using
: |>  a modified 'num_put' 'facet'. The intentation was to provide something
: |>  like the "Fortran 77 G edit dscriptor" (I don't know what this is
: |>  exactly but I know how to implement the framework for doing this...).
: |>  Of course, this can be seen as an abuse of locales but at least it
: |>  works.

: This is definitly an abuse of locales.

If I take the view that the locale "Fortran" (note that there is a
locale "C" which even has to be supported: lib.locale.cons paragraph 1)
should give me an environment where everything looks natural to a
Fortran programmer like the C locale does for C/C++ programmers, then I
would definitly call it not an abuse! In fact, locales are made to
encapsulate cultural differences, and this is exactly what is done :-)
Of course, locales are intended to encapsulate cultural difference
between nations and natural language but I can't really see that it is
such a definite abuse to encapsulate such artificial cultural
differences.

With regards to my 'f77g' manipulator the only thing which I would also
consider an abuse is the fact that this specific implementation
installs a new locale (I wrote and posted the code and later realized
that it shoud be done differently): The proper way would probably to
let the user install the locale and have the 'f77g' manipulator only an
effect if the "Fortran" locale or at least the corresponding facet is
installed.

Anyway, it is definitely not an abuse to install a different locale
than the default one, ie. the locale named "": After all, this is why
locales can be imbued. Thus, whether the 'f77g' manipulator is
considered an abuse or not, it is impossible to predict exactly what
the output would look like without knowledge of the imbued locale.

: Offhand, of course, I don't see
: anyway the standard could prevent it, and of course, the goal is to
: protect against Murphy, not Machiavelli.  I think that we would all
: agree that this is not the designed purpose of locale, and that during
: the design of locale, no effort was made to support this use.

The designed purpose of locale is to make it possible to encapsulate
cultural differences eg. resulting in differently formatted output. For
example, in financial programs it is often required that there are
thousend separators (comma or space) to be introduced. Such differences
are already supported by the standard facets but I think that the facet
mechanism is also designed to allow total new ways to format numbers!

: Steve's point was, of course, that overriding operator<< and operator>>
: would be an abuse of [io]stream as well.  Thus, during the design of
: [io]stream, no effort was made to support this use.  Since this use
: would require a special effort (declaring the operators virtual), the
: standard effectively prevents it.  I suspect, however, that it is more a
: question that no effort was made to support it, rather than an
: intentional effort made to thwart the Machiavellis who want to abuse
: iostream.

I suspect that it was a conscious decision not to make inserters and
extractors virtual in IOStreams (can anybody involved in the design of
IOStreams comment?). Otherwise there would be two competing reasons to
derive from these classes: On the one hand you want to derive to allow
convenient creation of streams writing to files, strings, etc., on the
other hand you want to derive to override the style eg. numbers are
formatted. Taking the details about formatting out of IOStreams makes
it orthogonal to change these details. There is another advantage of
this: Formatting is no longer bound to one specific application, ie.
immediate I/O with IOStreams. Instead, you can now eg. built a
different frontend to 'streambuf's for formatted I/O without having to
use the IOStream mechanism at all. Still it is possible to reuse the
formatting mechanism now placed in some facets (although it is still
necessary to provide an 'basic_ios' object as container for formatting
flags to the facets in question).

I think there is currently only relatively few experience with the
locale mechanism gathered since support for it came up relatively
recent. I can imagine several uses of locales, especially of the
virtual function mechanism for the formatting functions, which are
probably not exactly what locales were intended for: Mostly, I want to
get a more "elegant" interface to the format specifiers of formatted
I/O and an emulation of the "positional argument" feature of some stdio
implementation (those on the "genstl" mailing list will recognize this
theme from some recent postings). However, I think it is too early to
state definitely that these would be abuse...
--
<mailto:dietmar.kuehl@uni-konstanz.de>
<http://www.informatik.uni-konstanz.de/~kuehl/>
I am a realistic optimist - that's why I appear to be slightly pessimistic
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: James Kanze <james-albert.kanze@vx.cit.alcatel.fr>
Date: 1997/03/06
Raw View
James Kanze <james-albert.kanze@vx.cit.alcatel.fr> writes:

|>  kuehl@uzwil.informatik.uni-konstanz.de (Dietmar Kuehl) writes:
|>
|>  |>  Steve Clamage (Stephen.Clamage@Eng.Sun.COM) wrote:
|>  |>  : Interestingly, the argument *against* making them virtual is the same.
|>  |>  : Suppose I write an extractor for MyClass:
|>  |>  :  ostream& operator<<(ostream& o, const MyClass& m) {
|>  |>  :   o << '[' << m.data1 << '\t' << m.data2 << ']';
|>  |>  :   return o;
|>  |>  :  }
|>  |>  : Because inserters are not virtual, I know exactly what the output format
|>  |>  : will look like, and in particular I know that any extractor I write can
|>  |>  : can depend on reading that format. If inserters were virtual, I could not
|>  |>  : depend on the output format, nor write an extractor that would be sure to
|>  |>  : work.
|>  |>
|>  |>  This argument cannot hold! It is impossible to predict exactly what the
|>  |>  output format will look like since it depends on the 'locale' currently
|>  |>  being used. I posted yesterday an article to comp.lang.c++.moderated
|>  |>  describing a style how to modify the output behavior for 'double' using
|>  |>  a modified 'num_put' 'facet'. The intentation was to provide something
|>  |>  like the "Fortran 77 G edit dscriptor" (I don't know what this is
|>  |>  exactly but I know how to implement the framework for doing this...).
|>  |>  Of course, this can be seen as an abuse of locales but at least it
|>  |>  works.
|>
|>  This is definitly an abuse of locales.

Following up to my own post, but I've been thinking more about this.

Whether this particular use is an abuse or no is completely irrelevant
to the question.  Dietmar's point holds; num_put and num_get will behave
differently in different locales, for whatever reasons.

An obvious typical case: complex.  Operator<< outputs '(r,i)', and
operator>> expects to find the sequence '(', double, ',', double, ')' on
input, using "operator>>( istream& , double )" to parse and extract the
doubles.  Now suppose a program outputs the complex value (1.0,2.0) with
ios::floatfields == ios::fixed and ios::precision == 0.  The resulting
string will be "(1,2)".  Which ISN'T going to parse on input in most
locale's.

This leads me to several conclusions:

1.  If your class contains any floating point values, any monetory
values, any dates and probably any text strings, you'd better make it
locale dependant.

2.  It's going to be *very* difficult to design extractors which can
read data without knowing the precise locale under which it was
written.

--
James Kanze      home:     kanze@gabi-soft.fr        +33 (0)1 39 55 85 62
                 office:   kanze@vx.cit.alcatel.fr   +33 (0)1 69 63 14 54
GABI Software, Sarl., 22 rue Jacques-Lemercier, F-78000 Versailles France
     -- Conseils en informatique industrielle --
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: Stephen.Clamage@Eng.Sun.COM (Steve Clamage)
Date: 1997/03/03
Raw View
In article VAA10492@proxy3.ba.best.com, "marian" <marian@shellx.best.com> writes:
>Please post on comp.std.c++
>
>I heard that they considered making inserters and extractors virtual
>in iostreams.
>   Why was this suggested?
>   Why was this not done?

The question about virtual inserters/extractors comes up from time
to time, and indeed it was discussed at least once by the library
working group within the C++ committee.

The main argument in favor of making them virtual is to allow
you to derive a class from istream or ostream and get polymorphic
behavior. Iostream functions accept or return references to istream
or ostream, not to my_istream or my_ostream, and without the virtual
functions, derivation doesn't have the right behavior.

Interestingly, the argument *against* making them virtual is the same.
Suppose I write an extractor for MyClass:
 ostream& operator<<(ostream& o, const MyClass& m) {
  o << '[' << m.data1 << '\t' << m.data2 << ']';
  return o;
 }
Because inserters are not virtual, I know exactly what the output format
will look like, and in particular I know that any extractor I write can
can depend on reading that format. If inserters were virtual, I could not
depend on the output format, nor write an extractor that would be sure to work.

Clearly, these arguments can go around and around. The original design
of iostreams made the functions non-virtual, meaning that you usually
don't derive from istream or ostream for the purpose of getting different
inserter/extractor behavior. The C++ committee decided not to
change that basic design decision.
---
Steve Clamage, stephen.clamage@eng.sun.com
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: kuehl@uzwil.informatik.uni-konstanz.de (Dietmar Kuehl)
Date: 1997/03/04
Raw View
Hi,
Steve Clamage (Stephen.Clamage@Eng.Sun.COM) wrote:
: Interestingly, the argument *against* making them virtual is the same.
: Suppose I write an extractor for MyClass:
:  ostream& operator<<(ostream& o, const MyClass& m) {
:   o << '[' << m.data1 << '\t' << m.data2 << ']';
:   return o;
:  }
: Because inserters are not virtual, I know exactly what the output format
: will look like, and in particular I know that any extractor I write can
: can depend on reading that format. If inserters were virtual, I could not
: depend on the output format, nor write an extractor that would be sure to
: work.

This argument cannot hold! It is impossible to predict exactly what the
output format will look like since it depends on the 'locale' currently
being used. I posted yesterday an article to comp.lang.c++.moderated
describing a style how to modify the output behavior for 'double' using
a modified 'num_put' 'facet'. The intentation was to provide something
like the "Fortran 77 G edit dscriptor" (I don't know what this is
exactly but I know how to implement the framework for doing this...).
Of course, this can be seen as an abuse of locales but at least it
works.

Anyway, although this argument removes your argument, it just provides
a new argument why there should be no virtual inserters/extractors in
'ostream'/'istream': In some sense, these *are* already virtual! The
formatting of built-in types is ultimately done by the (virtual) member
'do_put()' of the 'num_put' 'facet' and, correspondingly, the
extraction is ultimately done bu the (virtual) member 'do_get()' of the
'num_get' 'facet'. Overloading these functions in a new 'facet' and
installing a corresponding 'locale' will modify the output behavior.

The interesting part is that this can also work for user defined types
which cannot have a virtual insertor/extractor anyway since they are no
members of 'ostream' or 'istream' (and it would be real bad idea to
derive classes from 'ostream' or 'istream' to make them some!): You can
just install a corresponding 'facet' into some 'locale' and install
this 'locale' with the corresponding stream. Here is a brief outline:

  class myclass { /*...*/ };

  // Facet doing the actual formatting/scanning:
  class myclass_io: public std::facet
  {
  public:
    typedef istreambuf_iterator<char> in_iter_type;
    typedef ostreambuf_iterator<char> out_iter_type;

    std::locale::id id; // required for every 'facet'!

    in_iter_type get(in_iter_type in, in_iter_type end,
       ios_base&stream, ios_base::iostate& err, myclass& v) const
    { return do_get(in, end, stream, err, v); }
    out_iter_type put(out_iter_type out, ios_base&stream,
       char_type fill, myclass const &v) const
    { return do_put(out, stream, fill, v); }

  protected:
    virtual in_iter_type do_get(in_iter_type in, in_iter_type end,
       ios_base&, ios_base::iostate& err, myclass& v) const
    { /* default implementation goes here */ }
    virtual out_iter_type put(out_iter_type out, ios_base&stream,
       char_type fill, myclass const &v) const
    { /* default implementation goes here */ }
  };

  // If the locale does not have the facet use this one:
  static myclass_io myclass_default_io;

  // I just show how an extractor might look like:
  istream &operator>> (istream &in, myclass &v)
  {
    // the facet uses this iterator type to read chars:
    typedef myclass_io::in_iter_type inIt;

    // prepare the stream (e.g. skip whitespace):
    istream::sentry cerberos(in)

    // if the stream is OK, attempt to extract the stuff:
    if (cerberos)
    {
      ios_base::iostate err = ios_base::goodbit;
      myclass           tmp;

      // now read using either the facet installed with the locale or
      // the default facet:
      if (has_facet<myclass_io>(in.getloc()))
 use_facet<myclass_io>(in.getloc()).get(inIt(in), inIt, in, err, tmp);
      else
 myclass_default_io.get(inIt(in), inIt, in, err, tmp);

      // if read was successful, set the value, other wise indicate an
      // error:
      if (err == ios_base::goodbit)
 v = tmp;
      else
 in.setstate(err);
    }

    return in;
  }

(hm, it turned out to not that brief as I intended...)

Well, this does not look as simple as a "normal" extractor, especially
since this whole thing is not even present in a "normal" extractor at
all! ... but it allows the user to override the way an object is read
and a corresponding inserter would allow the the user to override the
way the object is formatted. Anyway: There is no real need for virtual
inserters/extractors.

With the introduction of locales, 'istream' and 'ostream' became merely
the basis of a common interface for extractors and inserters,
respectively: The actual access to the "external representation" (e.g.
a file or a 'string') is done by a class derived from 'streambuf' while
the actual formatting/scanning is done by a 'facet' installed with the
'locale'. This combines a simple and common interface (the extractors
and inserters) with the flexibility to use any external representation
(by deriving form 'streambuf) and arbitrary formatting (using
'locale's). This is an ideal only rarely achieve: Full flexibility
while also providing ease of use. The only (IMO minor) drawback of this
approach is a potential loss in efficiency (I can't tell whether there
really will be a real loss in efficiency since I haven't profiled any
code using locales).
--
<mailto:dietmar.kuehl@uni-konstanz.de>
<http://www.informatik.uni-konstanz.de/~kuehl/>
I am a realistic optimist - that's why I appear to be slightly pessimistic
---
[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: James Kanze <james-albert.kanze@vx.cit.alcatel.fr>
Date: 1997/03/07
Raw View
kuehl@uzwil.informatik.uni-konstanz.de (Dietmar Kuehl) writes:

|>  Hi,
|>  James Kanze (james-albert.kanze@vx.cit.alcatel.fr) wrote:
|>  : kuehl@uzwil.informatik.uni-konstanz.de (Dietmar Kuehl) writes:
|>
|>  : |>  Steve Clamage (Stephen.Clamage@Eng.Sun.COM) wrote:
|>  : |>  : Interestingly, the argument *against* making them virtual is the
|>  : |>  : same. Suppose I write an extractor for MyClass:
|>  : |>  :  ostream& operator<<(ostream& o, const MyClass& m) {
|>  : |>  :   o << '[' << m.data1 << '\t' << m.data2 << ']';
|>  : |>  :   return o;
|>  : |>  :  }
|>  : |>  : Because inserters are not virtual, I know exactly what the output
|>  : |>  : format will look like, and in particular I know that any extractor
|>  : |>  : I write can can depend on reading that format. If inserters were
|>  : |>  : virtual, I could not depend on the output format, nor write an
|>  : |>  : extractor that would be sure to work.
|>  : |>
|>  : |>  This argument cannot hold! It is impossible to predict exactly what
|>  : |>  the output format will look like since it depends on the 'locale'
|>  : |>  currently being used. I posted yesterday an article to
|>  : |>  comp.lang.c++.moderated describing a style how to modify the output
|>  : |>  behavior for 'double' using a modified 'num_put' 'facet'. The
|>  : |>  intentation was to provide something like the "Fortran 77 G edit
|>  : |>  dscriptor" (I don't know what this is exactly but I know how to
|>  : |>  implement the framework for doing this...). Of course, this can be
|>  : |>  seen as an abuse of locales but at least it works.
|>
|>  : This is definitly an abuse of locales.
|>
|>  If I take the view that the locale "Fortran" (note that there is a
|>  locale "C" which even has to be supported: lib.locale.cons paragraph 1)
|>  should give me an environment where everything looks natural to a
|>  Fortran programmer like the C locale does for C/C++ programmers, then I
|>  would definitly call it not an abuse! In fact, locales are made to
|>  encapsulate cultural differences, and this is exactly what is done :-)
|>  Of course, locales are intended to encapsulate cultural difference
|>  between nations and natural language but I can't really see that it is
|>  such a definite abuse to encapsulate such artificial cultural
|>  differences.

As I point out in a followup to my own posting, whether it is an abuse
or not is really irrelevant to the original question.  Your point that
the exact text will depend on locale is well taken.  Regardless of the
"Fortran" formatting issue, there are certainly legitimate uses of
locale that will have similar effects.  (Well, I would consider "france"
or "germany" legitimate locales.  And floating point values will
generally use a ',', rather than a '.' in these locale's.)

I can even consider a legitimate use of a Fortran (sub-)locale.  Fortran
(and C) programmers, even in France and Germany, are used to seeing a
'.' as the decimal point, so a "french-fortran-programmers" locale, with
everything as in "french" except for the decimal character, might be
appropriate.

|>  With regards to my 'f77g' manipulator the only thing which I would also
|>  consider an abuse is the fact that this specific implementation
|>  installs a new locale (I wrote and posted the code and later realized
|>  that it shoud be done differently): The proper way would probably to
|>  let the user install the locale and have the 'f77g' manipulator only an
|>  effect if the "Fortran" locale or at least the corresponding facet is
|>  installed.

Precisely.  A program which decides: I want to format things
differently, so I'll just change the locale, is abusing it.  A user who
decides that, despite being in France, he wants to see floating point
output as Fortran intended, and installs a locale to do so, is fully
within his rights, and a program that DOESN'T use the new locale is
broken (IMHO).

At least in theory.  I think that there is room for discussion, and
border cases.  For example, if I'm outputting email headers, I'm
definitly going to set the locale to "C" before doing so, and reset it
to its former value afterwards.  (Formally, this is wrong, and I should
set it to a special email-header locale.  In practice, the "C" locale in
ALL C/C++ compilers I've ever seen is quite appropriate for
email-headers.)

|>  Anyway, it is definitely not an abuse to install a different locale
|>  than the default one, ie. the locale named "": After all, this is why
|>  locales can be imbued. Thus, whether the 'f77g' manipulator is
|>  considered an abuse or not, it is impossible to predict exactly what
|>  the output would look like without knowledge of the imbued locale.

Correct.  I reacted to your particular example (which I still think is
abuse), and not the point you were making, which is definitely valid.

|>  : Offhand, of course, I don't see
|>  : anyway the standard could prevent it, and of course, the goal is to
|>  : protect against Murphy, not Machiavelli.  I think that we would all
|>  : agree that this is not the designed purpose of locale, and that during
|>  : the design of locale, no effort was made to support this use.
|>
|>  The designed purpose of locale is to make it possible to encapsulate
|>  cultural differences eg. resulting in differently formatted output. For
|>  example, in financial programs it is often required that there are
|>  thousend separators (comma or space) to be introduced. Such differences
|>  are already supported by the standard facets but I think that the facet
|>  mechanism is also designed to allow total new ways to format numbers!

I'm sure it is.  For example, in locale "arabic", I won't even see my
so-called arabic numbers, but either a multibyte sequence or (in a
wchar_t locale) a totally different sequence of ten codes.  (I'd make my
usual quip about programs not being able to handle this being broken,
but in this respect, I don't know of any programs which aren't broken,
including my own.)

In theory, this shouldn't be a problem; if you output a double in an
arabic locale, you should be able to input it in the same locale; the
fact that you, the programmer, can't make any sense out of the
characters on the disk is irrelevant.  In practice, it doesn't quite
work out that way; see my example of complex in my other posting.

|>  : Steve's point was, of course, that overriding operator<< and operator>>
|>  : would be an abuse of [io]stream as well.  Thus, during the design of
|>  : [io]stream, no effort was made to support this use.  Since this use
|>  : would require a special effort (declaring the operators virtual), the
|>  : standard effectively prevents it.  I suspect, however, that it is more a
|>  : question that no effort was made to support it, rather than an
|>  : intentional effort made to thwart the Machiavellis who want to abuse
|>  : iostream.
|>
|>  I suspect that it was a conscious decision not to make inserters and
|>  extractors virtual in IOStreams (can anybody involved in the design of
|>  IOStreams comment?).

I believe that Steve Clamage actually said that the issue had been
discussed, so there was definitly a conscious decision.

I agree with this decision.  A class isn't automatically extendable,
just because it is written in C++.  I must be designed for
extendability.  In the case of [io]stream, extendability is offered in
several directions:

1. The actual sinking and sourcing of characters is decoupled from the
formatting; the user can provide a new streambuf (and streambuf is
extensible through inheritance).

2. The class is explicitly designed so that the user can add new
operator<< and >>.

3. The class is a template, so can be used on user defined character
types.

IMHO, allowing extension through inheritance would compromize 2, which
is more important (in this particular case).  While 2 is compromized
somewhat by locale's, I think that in practice (if not in theory), this
will not turn out to be a grand problem.  The variations due to locale
are all perversive, and not just in iostream; if the program is designed
with them in mind, adding the necessary code in the user defined << and
>> is just part of the job.  If not, it won't run in strange locales,
period.

--
James Kanze      home:     kanze@gabi-soft.fr        +33 (0)1 39 55 85 62
                 office:   kanze@vx.cit.alcatel.fr   +33 (0)1 69 63 14 54
GABI Software, Sarl., 22 rue Jacques-Lemercier, F-78000 Versailles France
     -- Conseils en informatique industrielle --
---
[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: "marian" <marian@shellx.best.com>
Date: 1997/02/26
Raw View
Please post on comp.std.c++

I heard that they considered making inserters and extractors virtual
in iostreams.
   Why was this suggested?
   Why was this not done?

Marian
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]