ostream operator<< and builtin types

Discussion in 'C++' started by Erik Wikström, Feb 6, 2008.

  1. Accordin to the standard it is possible for
    basic_ostream::eek:perator<<(T val), where T is a builtin arithmetic
    type, to fail (and optionally throw an exception. I've been trying to
    track down what would cause << to fail but have not yet been
    successful, what I really want to know is whether one should bother
    looking for exceptions when using code such as this to convert
    arithmetic types to strings:

    template<typename T>
    std::string atos(const T& v)
    {
    std::eek:stringstream os;
    if (!(os << v))
    throw std::runtime_exception("Failed to convert value");
    return os.str();
    }

    While I realise that it might be a good idea to check when converting
    user defined types I hope/assume that there are no implementations out
    there that would fail to convert the builtin arithmetic types (except
    under such conditions that further execution probably will not be
    possible anyway). Is this a correct assumption?

    --
    Erik Wikström
    Erik Wikström, Feb 6, 2008
    #1
    1. Advertising

  2. Erik Wikström

    Jim Langston Guest

    Erik Wikström wrote:
    > Accordin to the standard it is possible for
    > basic_ostream::eek:perator<<(T val), where T is a builtin arithmetic
    > type, to fail (and optionally throw an exception. I've been trying to
    > track down what would cause << to fail but have not yet been
    > successful, what I really want to know is whether one should bother
    > looking for exceptions when using code such as this to convert
    > arithmetic types to strings:
    >
    > template<typename T>
    > std::string atos(const T& v)
    > {
    > std::eek:stringstream os;
    > if (!(os << v))
    > throw std::runtime_exception("Failed to convert value");
    > return os.str();
    > }
    >
    > While I realise that it might be a good idea to check when converting
    > user defined types I hope/assume that there are no implementations out
    > there that would fail to convert the builtin arithmetic types (except
    > under such conditions that further execution probably will not be
    > possible anyway). Is this a correct assumption?


    Consider, you are using operator<< to write to a disk file on a floppy
    opened with ofstream which derives form basic_ostream (I believe). While
    writing, the floppy becomes full, or someone removes it from the drive.

    Or the hard drive becomes full. Or has a bad sector that gives a writing
    error. Etc...

    If this happens in your program, what do you want to happen? What do you
    want to happen if you are writing some data to a file and the user removes
    the floppy? That will tell you if you want to handle the exceptions or not.
    Do you want your program to crash, or show an error box asking them to put
    the floppy back in, do you want to re-write the last data attempted or the
    entire file again or... if one size fit all we would't need exceptions.


    --
    Jim Langston
    Jim Langston, Feb 6, 2008
    #2
    1. Advertising

  3. Erik Wikström

    Pavel Shved Guest

    On 6 фев, 13:48, "Erik Wikström" <> wrote:
    > Accordin to the standard it is possible for
    > basic_ostream::eek:perator<<(T val), where T is a builtin arithmetic
    > type, to fail (and optionally throw an exception. I've been trying to
    > track down what would cause << to fail but have not yet been
    > successful, what I really want to know is whether one should bother
    > looking for exceptions when using code such as this to convert
    > arithmetic types to strings...


    One should. And one sould do it even in common implementations.

    iostream conversions use locale abstractions to handle output complied
    with national pecularities. According to standard, locale functions
    may throw (much time has passed since i was trying to track it, so
    you'd better research it again). And now assume that we are in the
    locale of Mbongo-bongo savage tribe which has no representation of
    numbers but integers from 1 to 10, or in medieval locale where 666 is
    banned from being printed. The most straightforward solution here is
    to throw an exception (bad_heretic, for example).

    Or, to be more simple, if we're in envronment that has no IEEE-
    compliant floating point aritmetical subsystem hence the
    implementation doesn't know about NaNs, infinities etc and just fails
    to print them.
    Pavel Shved, Feb 7, 2008
    #3
  4. Erik Wikström

    James Kanze Guest

    On Feb 6, 11:48 am, "Erik Wikström" <> wrote:
    > Accordin to the standard it is possible for
    > basic_ostream::eek:perator<<(T val), where T is a builtin
    > arithmetic type, to fail (and optionally throw an exception.
    > I've been trying to track down what would cause << to fail but
    > have not yet been successful, what I really want to know is
    > whether one should bother looking for exceptions when using
    > code such as this to convert arithmetic types to strings:


    > template<typename T>
    > std::string atos(const T& v)
    > {
    > std::eek:stringstream os;
    > if (!(os << v))
    > throw std::runtime_exception("Failed to convert value");
    > return os.str();
    > }


    > While I realise that it might be a good idea to check when
    > converting user defined types I hope/assume that there are no
    > implementations out there that would fail to convert the
    > builtin arithmetic types (except under such conditions that
    > further execution probably will not be possible anyway). Is
    > this a correct assumption?


    No.

    I'm not sure that an operator<< has the right to set
    failbit---the standard operator<< for basic types don't---, but
    anytime the streambuf returns a failure from the attempt to
    write, or throws an exception, the conversion routines should
    set badbit. In the case of ostringstream, this will probably
    only occur as a result of std::bad_alloc, but as Jim Langston
    pointed out, with ofstream, there can be other causes as well.

    Note too that with ofstream, the error might not be detected
    immediately, because of buffering. You can't be sure that the
    output has succeeded until after close(). And that in your
    case, bad_alloc can also hit the copy constructor used to return
    the value, so you have to be prepared for that anyway.

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
    James Kanze, Feb 7, 2008
    #4
  5. Erik Wikström

    James Kanze Guest

    On Feb 7, 7:29 am, Pavel Shved <> wrote:
    > On 6 ???, 13:48, "Erik Wikström" <> wrote:
    >
    > > Accordin to the standard it is possible for
    > > basic_ostream::eek:perator<<(T val), where T is a builtin arithmetic
    > > type, to fail (and optionally throw an exception. I've been trying to
    > > track down what would cause << to fail but have not yet been
    > > successful, what I really want to know is whether one should bother
    > > looking for exceptions when using code such as this to convert
    > > arithmetic types to strings...


    > One should. And one sould do it even in common implementations.


    Because of badbit, of course. You can't get failbit.

    > iostream conversions use locale abstractions to handle output complied
    > with national pecularities. According to standard, locale functions
    > may throw (much time has passed since i was trying to track it, so
    > you'd better research it again). And now assume that we are in the
    > locale of Mbongo-bongo savage tribe which has no representation of
    > numbers but integers from 1 to 10, or in medieval locale where 666 is
    > banned from being printed. The most straightforward solution here is
    > to throw an exception (bad_heretic, for example).


    According to the standard, any function can throw anything for
    any reason at all, with very few exceptions. From a quality of
    implementation point of view, I would avoid implementations
    which throw doubles just because it's Friday the 13th. The
    standard specifies the behavior of std::num_put pretty closely,
    and there's really no reason for it to throw. (A conforming
    implementation cannot, for example, is required to generate
    output in the specified base, and canot refused to convert 666.)

    > Or, to be more simple, if we're in envronment that has no IEEE-
    > compliant floating point aritmetical subsystem hence the
    > implementation doesn't know about NaNs, infinities etc and just fails
    > to print them.


    If the environment doesn't have IEEE floating point, it can't
    have infinities and NaNs to output, so the problem doesn't
    arise.

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
    James Kanze, Feb 7, 2008
    #5
  6. Erik Wikström

    Jerry Coffin Guest

    In article <2e177050-de98-4af3-a477-
    >,
    says...
    > On Feb 7, 7:29 am, Pavel Shved <> wrote:


    [ ... ]

    > > Or, to be more simple, if we're in envronment that has no IEEE-
    > > compliant floating point aritmetical subsystem hence the
    > > implementation doesn't know about NaNs, infinities etc and just fails
    > > to print them.

    >
    > If the environment doesn't have IEEE floating point, it can't
    > have infinities and NaNs to output, so the problem doesn't
    > arise.


    I suspect he's talking about a situation where the hardware is (at least
    partially) IEEE-compliant, so it can produce NaNs and infinities, but
    the surrounding software is not so compliant, so it doesn't know what to
    do when they're encountered. Even though it's only a guess about his
    situation, it's certainly a situation I've encountered in the past.

    Just FWIW, there were also a number of versions of pre-IEEE floating
    point that had bit patterns that corresponded (at least roughly) to
    infinities, NaNs, etc. TTBOMK, the earliest was Conrad Zuse's Z1, back
    in 1941 or so (it had something roughly that acted essentially the same
    as a quiet NaN). The IBM stretch and CDC mainframes starting with the
    CDC 6600 incorporated roughly similar ideas as well (though I'm pretty
    sure there was never an implementation of C, much less C++, for any of
    those).

    --
    Later,
    Jerry.

    The universe is a figment of its own imagination.
    Jerry Coffin, Feb 17, 2008
    #6
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Lonnie Princehouse

    Overriding builtin types

    Lonnie Princehouse, Mar 5, 2004, in forum: Python
    Replies:
    0
    Views:
    345
    Lonnie Princehouse
    Mar 5, 2004
  2. =?iso-8859-1?q?Erik_Wikstr=F6m?=

    Pointer to operator for builtin types

    =?iso-8859-1?q?Erik_Wikstr=F6m?=, Dec 15, 2006, in forum: C++
    Replies:
    6
    Views:
    359
    =?iso-8859-1?q?Erik_Wikstr=F6m?=
    Dec 15, 2006
  3. Replies:
    2
    Views:
    1,879
  4. bdb112
    Replies:
    2
    Views:
    287
    Chris Torek
    Jul 2, 2011
  5. Amirouche B.
    Replies:
    5
    Views:
    217
    Amirouche B.
    Aug 23, 2011
Loading...

Share This Page