Calling function that may throw an exception

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Eric Lilja

    Calling function that may throw an exception

    Hello, I'm working with a hash table that is encapsulated in a class. One of
    its member functions insert() throws an exception
    if the insertion fails (for example, if the value was already present in the
    hash table). Now I have client code that looks like this:

    bool exception_throw n = false;

    try
    {
    hash_table.inse rt(some_value);
    }
    catch(const std::runtime_er ror& e)
    {
    std::cerr << e.what() << std::endl;

    exception_throw n = true;
    }

    if(!exception_t hrown)
    {
    std::cout << some_value << " successfully inserted." << std::endl; /* For
    debugging purposes, it would be nice to see position here */
    }

    Using the flag variable exception_throw n strikes me as a bit ugly...how
    should I deal with this? If I'm calling a function that
    may throw an exception I want to catch that exception. I can change the hash
    table class itself if I need to..maybe the insert()
    member function should return some error code instead but runtime_error
    seems a bit more convenient since it can (should I think)
    contain a description of the error. Please advise.

    / Eric


  • Victor Bazarov

    #2
    Re: Calling function that may throw an exception

    Eric Lilja wrote:[color=blue]
    > Hello, I'm working with a hash table that is encapsulated in a class. One of
    > its member functions insert() throws an exception
    > if the insertion fails (for example, if the value was already present in the
    > hash table). Now I have client code that looks like this:
    >
    > bool exception_throw n = false;
    >
    > try
    > {
    > hash_table.inse rt(some_value);
    > }
    > catch(const std::runtime_er ror& e)
    > {
    > std::cerr << e.what() << std::endl;
    >
    > exception_throw n = true;
    > }
    >
    > if(!exception_t hrown)
    > {
    > std::cout << some_value << " successfully inserted." << std::endl; /* For
    > debugging purposes, it would be nice to see position here */
    > }
    >
    > Using the flag variable exception_throw n strikes me as a bit ugly...how
    > should I deal with this? If I'm calling a function that
    > may throw an exception I want to catch that exception. I can change the hash
    > table class itself if I need to..maybe the insert()
    > member function should return some error code instead but runtime_error
    > seems a bit more convenient since it can (should I think)
    > contain a description of the error. Please advise.[/color]

    There was a discussion here recently "Arguments *Against* Exception Use".
    Check it out. There was the note by Herb Sutter reminding us that one
    shouldn't confuse normal functionality (and processing thereof) with
    exceptional situations. If your hash table is _allowed_ to indicate that
    insertion didn't happen and that's normal, then it has to be a return code
    and not an exception. Something like that, anyway.

    V

    Comment

    • Alf P. Steinbach

      #3
      Re: Calling function that may throw an exception

      * Victor Bazarov:[color=blue]
      > Eric Lilja wrote:[color=green]
      > > Hello, I'm working with a hash table that is encapsulated in a class. One of
      > > its member functions insert() throws an exception
      > > if the insertion fails (for example, if the value was already present in the
      > > hash table). Now I have client code that looks like this:
      > >
      > > bool exception_throw n = false;
      > >
      > > try
      > > {
      > > hash_table.inse rt(some_value);
      > > }
      > > catch(const std::runtime_er ror& e)
      > > {
      > > std::cerr << e.what() << std::endl;
      > >
      > > exception_throw n = true;
      > > }
      > >
      > > if(!exception_t hrown)
      > > {
      > > std::cout << some_value << " successfully inserted." << std::endl; /* For
      > > debugging purposes, it would be nice to see position here */
      > > }
      > >
      > > Using the flag variable exception_throw n strikes me as a bit ugly...how
      > > should I deal with this? If I'm calling a function that
      > > may throw an exception I want to catch that exception. I can change the hash
      > > table class itself if I need to..maybe the insert()
      > > member function should return some error code instead but runtime_error
      > > seems a bit more convenient since it can (should I think)
      > > contain a description of the error. Please advise.[/color]
      >
      > There was a discussion here recently "Arguments *Against* Exception Use".
      > Check it out. There was the note by Herb Sutter reminding us that one
      > shouldn't confuse normal functionality (and processing thereof) with
      > exceptional situations. If your hash table is _allowed_ to indicate that
      > insertion didn't happen and that's normal, then it has to be a return code
      > and not an exception. Something like that, anyway.[/color]

      It's very easy to have both.

      In terms of both efficiency and simplicity the best is to build the
      exception-throwing one as a wrapper around the return-code one.

      But I remember I argued at least halfway successfully once for doing
      it the opposite way when a higher layer calls a lower layer of software.
      The reason for that is that what is an exception at a lower layer
      (e.g. unable to send mail) at some higher level becomes an expected and
      quite normal thing (e.g. report that to the user). But the argument is
      mostly for trolling purposes, because the assumption that both these
      layers are involved in the same design is not a well-founded one... ;-)

      --
      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?

      Comment

      • John Harrison

        #4
        Re: Calling function that may throw an exception


        "Eric Lilja" <ericlilja_remo ve_this@yahoo.c om> wrote in message
        news:cnaqb7$pk8 $1@news.island. liu.se...[color=blue]
        > Hello, I'm working with a hash table that is encapsulated in a class. One
        > of its member functions insert() throws an exception
        > if the insertion fails (for example, if the value was already present in
        > the hash table). Now I have client code that looks like this:
        >
        > bool exception_throw n = false;
        >
        > try
        > {
        > hash_table.inse rt(some_value);
        > }
        > catch(const std::runtime_er ror& e)
        > {
        > std::cerr << e.what() << std::endl;
        >
        > exception_throw n = true;
        > }
        >
        > if(!exception_t hrown)
        > {
        > std::cout << some_value << " successfully inserted." << std::endl; /*
        > For debugging purposes, it would be nice to see position here */
        > }
        >
        > Using the flag variable exception_throw n strikes me as a bit ugly...how
        > should I deal with this?[/color]

        Well you can certainly simplify the code, no flag is needed

        try
        {
        hash_table.inse rt(some_value);
        std::cout << some_value << " successfully inserted." << std::endl;
        }
        catch(const std::runtime_er ror& e)
        {
        std::cerr << e.what() << std::endl;
        }
        [color=blue]
        > If I'm calling a function that
        > may throw an exception I want to catch that exception. I can change the
        > hash table class itself if I need to..maybe the insert()
        > member function should return some error code instead but runtime_error
        > seems a bit more convenient since it can (should I think)
        > contain a description of the error. Please advise.
        >[/color]

        insert() could return a status object that contains the error message if
        things go wrong.

        john


        Comment

        • Eric Lilja

          #5
          Re: Calling function that may throw an exception


          "Victor Bazarov" <v.Abazarov@com Acast.net> wrote in message
          news:Yk6md.1094 5$Ae.5142@newsr ead1.dllstx09.u s.to.verio.net. ..[color=blue]
          > Eric Lilja wrote:[color=green]
          >> Hello, I'm working with a hash table that is encapsulated in a class. One
          >> of its member functions insert() throws an exception
          >> if the insertion fails (for example, if the value was already present in
          >> the hash table). Now I have client code that looks like this:
          >>
          >> bool exception_throw n = false;
          >>
          >> try
          >> {
          >> hash_table.inse rt(some_value);
          >> }
          >> catch(const std::runtime_er ror& e)
          >> {
          >> std::cerr << e.what() << std::endl;
          >>
          >> exception_throw n = true;
          >> }
          >>
          >> if(!exception_t hrown)
          >> {
          >> std::cout << some_value << " successfully inserted." << std::endl; /*
          >> For debugging purposes, it would be nice to see position here */
          >> }
          >>
          >> Using the flag variable exception_throw n strikes me as a bit ugly...how
          >> should I deal with this? If I'm calling a function that
          >> may throw an exception I want to catch that exception. I can change the
          >> hash table class itself if I need to..maybe the insert()
          >> member function should return some error code instead but runtime_error
          >> seems a bit more convenient since it can (should I think)
          >> contain a description of the error. Please advise.[/color]
          >
          > There was a discussion here recently "Arguments *Against* Exception Use".
          > Check it out. There was the note by Herb Sutter reminding us that one
          > shouldn't confuse normal functionality (and processing thereof) with
          > exceptional situations. If your hash table is _allowed_ to indicate that
          > insertion didn't happen and that's normal, then it has to be a return code
          > and not an exception. Something like that, anyway.
          >
          > V[/color]

          Thanks for the reply. Say I change the hash table to return an error code
          instead of
          throwing an exception when the user is trying to insert a value that is
          already present
          in the hash table (a situation that strikes me as a bit too common to be
          called exceptional),
          what sort of a mechanism should I implement alongside it if the user wants a
          more detailed
          error description (could be useful for debugging purposes)?

          I haven't checked out the thread you mentioned yet, but I will.

          / Eric


          Comment

          • Eric Lilja

            #6
            Re: Calling function that may throw an exception


            "John Harrison" <john_andronicu s@hotmail.com> wrote in message
            news:2vsauuF2p3 551U1@uni-berlin.de...[color=blue]
            >
            > "Eric Lilja" <ericlilja_remo ve_this@yahoo.c om> wrote in message
            > news:cnaqb7$pk8 $1@news.island. liu.se...[color=green]
            >> Hello, I'm working with a hash table that is encapsulated in a class. One
            >> of its member functions insert() throws an exception
            >> if the insertion fails (for example, if the value was already present in
            >> the hash table). Now I have client code that looks like this:
            >>
            >> bool exception_throw n = false;
            >>
            >> try
            >> {
            >> hash_table.inse rt(some_value);
            >> }
            >> catch(const std::runtime_er ror& e)
            >> {
            >> std::cerr << e.what() << std::endl;
            >>
            >> exception_throw n = true;
            >> }
            >>
            >> if(!exception_t hrown)
            >> {
            >> std::cout << some_value << " successfully inserted." << std::endl; /*
            >> For debugging purposes, it would be nice to see position here */
            >> }
            >>
            >> Using the flag variable exception_throw n strikes me as a bit ugly...how
            >> should I deal with this?[/color]
            >
            > Well you can certainly simplify the code, no flag is needed
            >
            > try
            > {
            > hash_table.inse rt(some_value);
            > std::cout << some_value << " successfully inserted." << std::endl;
            > }
            > catch(const std::runtime_er ror& e)
            > {
            > std::cerr << e.what() << std::endl;
            > }[/color]

            Wow, thanks John! After all this time spent learning C++ I never realised
            that I could put
            it in the same block after the call to the function-that-may-throw. Why
            didn't I think of that?
            Anyway, this new knowledge will clean up A LOT of my old programs > 100
            lines!! Thanks!
            [color=blue]
            >[color=green]
            >> If I'm calling a function that
            >> may throw an exception I want to catch that exception. I can change the
            >> hash table class itself if I need to..maybe the insert()
            >> member function should return some error code instead but runtime_error
            >> seems a bit more convenient since it can (should I think)
            >> contain a description of the error. Please advise.
            >>[/color]
            >
            > insert() could return a status object that contains the error message if
            > things go wrong.
            >[/color]

            Yeah, I'm thinking of changing the hash table class to do just that when the
            user
            is trying to perform an illegal insertion, which doesn't seem very
            exceptional to
            me. But as I said in my reply to Victor, I still would like the ability to
            get a more
            detailed error description, but how should I get that with numerical error
            codes?
            Some variant of errno but built-in in the class?
            [color=blue]
            > john
            >
            >[/color]

            / Eric


            Comment

            • Victor Bazarov

              #7
              Re: Calling function that may throw an exception

              Eric Lilja wrote:[color=blue]
              > [...] Say I change the hash table to return an error code
              > instead of
              > throwing an exception when the user is trying to insert a value that is
              > already present
              > in the hash table (a situation that strikes me as a bit too common to be
              > called exceptional),
              > what sort of a mechanism should I implement alongside it if the user wants a
              > more detailed
              > error description (could be useful for debugging purposes)?[/color]

              John has suggested it, and it seems like a decent solution, to return
              a reference to a static object of the class... Of course, you could
              easily marry the two concepts. It could be a pseudo-enumerator with
              the value/comments and a real object:

              template<class T>
              class inserter { // your hash table or anything, essentially
              class iterator {
              ...
              virtual const std::string& what() const {
              return inserter::every thingOK;
              }
              };

              static std::string everythingOK;
              static std::string insertionFailed ;
              static std::string otherError;

              class insertionFailed _iterator : public iterator {
              const std::string& what() const {
              return inserter::inser tionFailed;
              }
              };

              class otherError_iter ator : public iterator {
              ...
              };

              iterator insert(T t);
              };
              ...
              inserter<blah> mytable;

              inserter::itera tor it = mytable.insert( blah());
              if (it == inserter::inser tionFailed_iter ator) {
              // insertion failed
              }
              else {
              // use 'it' here
              }


              Victor

              Comment

              • E. Robert Tisdale

                #8
                Re: Calling function that may throw an exception

                Eric Lilja wrote:
                [color=blue]
                > I'm working with a hash table that is encapsulated in a class.
                > One of its member functions insert() throws an exception
                > if the insertion fails
                > (for example, if the value was already present in the hash table).
                > Now I have client code that looks like this:
                >
                > bool exception_throw n = false;
                >
                > try {
                > hash_table.inse rt(some_value);[/color]

                This is a bad example.
                The exception handling mechanism isn't necessary
                unless the try block evaluates non-trivial expressions
                with one or more operators that may throw exceptions.
                [color=blue]
                > }
                > catch(const std::runtime_er ror& e) {
                >
                > std::cerr << e.what() << std::endl;
                >
                > exception_throw n = true;
                > }
                >
                > if (!exception_thr own) {
                >
                > std::cout << some_value << " successfully inserted." << std::endl;
                > // For debugging purposes, it would be nice to see position here.
                > }
                >
                > Using the flag variable exception_throw n strikes me as a bit ugly...
                > how should I deal with this? If I'm calling a function that
                > may throw an exception I want to catch that exception.
                >
                > I can change the hash table class itself if I need to.
                > Maybe the insert() member function should return some error code instead
                > but runtime_error seems a bit more convenient
                > since it can (should I think) contain a description of the error.
                > Please advise.[/color]

                I think that you need to redesign your hash table class.
                Your insert(const SomeType&) method should return a value
                so that it can be used in expressions.
                It could return a reference to the has table object
                or it could return an exception object.
                Whether you decide to throw an exception of return an exception,
                the exception object must contain enough information
                about the exception to allow the calling program
                to handle the exception and recover.
                In this case, the exception object may contain a simple error code
                or even a boolean value which simply indicates whether or not
                the insertion failed. For example:

                bool HashTable::inse rt(const SomeType&) {
                // Return true if successful.
                }

                . . .

                if (hash_table.ins ert(some_value) ) {
                std::cout << some_value << "successful ly inserted."
                << std::endl;
                }

                Comment

                • Andre Kostur

                  #9
                  Re: Calling function that may throw an exception

                  "Eric Lilja" <ericlilja_remo ve_this@yahoo.c om> wrote in
                  news:cnat5k$r3o $1@news.island. liu.se:
                  [color=blue][color=green]
                  >> insert() could return a status object that contains the error message
                  >> if things go wrong.
                  >>[/color]
                  >
                  > Yeah, I'm thinking of changing the hash table class to do just that
                  > when the user
                  > is trying to perform an illegal insertion, which doesn't seem very
                  > exceptional to
                  > me. But as I said in my reply to Victor, I still would like the
                  > ability to get a more
                  > detailed error description, but how should I get that with numerical
                  > error codes?
                  > Some variant of errno but built-in in the class?[/color]

                  Assuming that insert returns an error code on failure (and 0 on success),
                  what "more detailed error description" could you want more than EEXIST?
                  (Not sure if errno.h is Standard or not.. might be POSIX).

                  If insert were only returning a bool, maybe... but only if there were
                  multiple reasons as to why the insert could fail....

                  Comment

                  • Markus Elfring

                    #10
                    Re: Calling function that may throw an exception

                    > what sort of a mechanism should I implement alongside it if the user wants a[color=blue]
                    > more detailed
                    > error description (could be useful for debugging purposes)?[/color]

                    Please consider that exceptions can not be ignored by the programmer
                    without additional instructions.
                    Would you like to guarantee that library users must react to a thrown
                    "notificati on"?

                    Regards,
                    Markus

                    Comment

                    • Markus Elfring

                      #11
                      Re: Calling function that may throw an exception

                      > But as I said in my reply to Victor, I still would like the ability to[color=blue]
                      > get a more
                      > detailed error description, but how should I get that with numerical error
                      > codes?
                      > Some variant of errno but built-in in the class?[/color]

                      Does the discussion "conversion : errno => exception" offer interesting
                      and useful informations for you?


                      Regards,
                      Markus

                      Comment

                      • Markus Elfring

                        #12
                        Re: Calling function that may throw an exception

                        > bool HashTable::inse rt(const SomeType&) {[color=blue]
                        > // Return true if successful.
                        > }[/color]

                        How easy is it to forget to check the return code?

                        Have you got resource limitations or constraints like in EC++ to
                        exclude the usage of exceptions?

                        Comment

                        • Michiel Salters

                          #13
                          Re: Calling function that may throw an exception

                          Markus.Elfring@ web.de (Markus Elfring) wrote in message news:<40ed1d8f. 0411161246.1b1a f161@posting.go ogle.com>...[color=blue][color=green]
                          > > bool HashTable::inse rt(const SomeType&) {
                          > > // Return true if successful.
                          > > }[/color]
                          >
                          > How easy is it to forget to check the return code?[/color]

                          Easy. However, there are situations in which it is reasonable
                          to use a bool return value to indicate duplicates. You definitely
                          need to keep that condition separate from std::bad_alloc.
                          Ignoring duplicates may be a sane strategy.

                          Regards,
                          Michiel Salters

                          Comment

                          Working...