Handling errors within templated classes

Discussion in 'C++' started by RichardOnRails, Oct 30, 2007.

  1. I have a Stack class that works fine. In particular, when it
    encounters an error, it cout's a msg and exits. However, I'd like to
    change it to report the error and continue with dummy data as
    necessary. My problem is how to construct dummy data consistent with
    the type the class was instantiated with.

    My class, stripped to it's essentials for my purpose here, is:

    template <class T>
    class Stack {
    public:
    T pop()
    {
    if ( top < 0 )
    {
    cout << "Error\n";
    return WHAT;
    }
    return st[top--];
    }
    private:
    int top;
    T st[5];
    };

    How might the "return WHAT;" statement be coded to yield something
    like:

    if ( typeof(T) == int
    doThis(0);
    else
    doThat("xxx");

    It was recommended by one person that I check out "template
    specialization", which I Googled. I found several offerings, but I
    don't think they were applicable to the situation I'm trying to
    address (but maybe I'm wrong).

    I'm running MinGW on WinXP-Pro/.SP2.

    Thanks in Advance,
    Richard
    RichardOnRails, Oct 30, 2007
    #1
    1. Advertising

  2. RichardOnRails

    Kai-Uwe Bux Guest

    RichardOnRails wrote:

    > I have a Stack class that works fine. In particular, when it
    > encounters an error, it cout's a msg and exits. However, I'd like to
    > change it to report the error and continue with dummy data as
    > necessary. My problem is how to construct dummy data consistent with
    > the type the class was instantiated with.
    >
    > My class, stripped to it's essentials for my purpose here, is:
    >
    > template <class T>
    > class Stack {
    > public:
    > T pop()
    > {
    > if ( top < 0 )
    > {
    > cout << "Error\n";
    > return WHAT;


    You can obtain a default value for T by using the default constructor
    (provided T has one):

    return ( T() );

    > }
    > return st[top--];
    > }
    > private:
    > int top;
    > T st[5];
    > };
    >
    > How might the "return WHAT;" statement be coded to yield something
    > like:
    >
    > if ( typeof(T) == int
    > doThis(0);
    > else
    > doThat("xxx");
    >
    > It was recommended by one person that I check out "template
    > specialization", which I Googled. I found several offerings, but I
    > don't think they were applicable to the situation I'm trying to
    > address (but maybe I'm wrong).


    I am not following the doThis() vs. doThat() example. In particular, I have
    no idea what the "xxx" is doing there.


    BTW: The stack class looks fishy. Poping off an empty stack should trigger
    an assert(). If you really want the program to continue, you may opt for
    throwing an exception. If you return invented data, client code has no
    chance detecting that there way an error.

    Also: a hard-coded limit size of 5 is (a) rather small and (b) not
    necessary at all. Why don't you use std::stack<>?


    Best

    Kai-Uwe Bux
    Kai-Uwe Bux, Oct 30, 2007
    #2
    1. Advertising

  3. On Oct 30, 1:20 am, Kai-Uwe Bux <> wrote:
    > RichardOnRails wrote:
    > > I have a Stack class that works fine. In particular, when it
    > > encounters an error, it cout's a msg and exits. However, I'd like to
    > > change it to report the error and continue with dummy data as
    > > necessary. My problem is how to construct dummy data consistent with
    > > the type the class was instantiated with.

    >
    > > My class, stripped to it's essentials for my purpose here, is:

    >
    > > template <class T>
    > > class Stack {
    > > public:
    > > T pop()
    > > {
    > > if ( top < 0 )
    > > {
    > > cout << "Error\n";
    > > return WHAT;

    >
    > You can obtain a default value for T by using the default constructor
    > (provided T has one):
    >
    > return ( T() );
    >
    >
    >
    > > }
    > > return st[top--];
    > > }
    > > private:
    > > int top;
    > > T st[5];
    > > };

    >
    > > How might the "return WHAT;" statement be coded to yield something
    > > like:

    >
    > > if ( typeof(T) == int
    > > doThis(0);
    > > else
    > > doThat("xxx");

    >
    > > It was recommended by one person that I check out "template
    > > specialization", which I Googled. I found several offerings, but I
    > > don't think they were applicable to the situation I'm trying to
    > > address (but maybe I'm wrong).

    >
    > I am not following the doThis() vs. doThat() example. In particular, I have
    > no idea what the "xxx" is doing there.
    >
    > BTW: The stack class looks fishy. Poping off an empty stack should trigger
    > an assert(). If you really want the program to continue, you may opt for
    > throwing an exception. If you return invented data, client code has no
    > chance detecting that there way an error.
    >
    > Also: a hard-coded limit size of 5 is (a) rather small and (b) not
    > necessary at all. Why don't you use std::stack<>?
    >
    > Best
    >
    > Kai-Uwe Bux


    Hi Kai-Uwe,

    Thanks for your response.

    Your questions/suggestions are well founded. However, I was using a
    "toy" application to test alternative error-handling strategies. One
    was to trap the error, display a msg and exit the app. However,
    sometimes it's desirable to recover somehow from errors so that
    additional errors can be exposed in a single pass through all the
    calls in an app.

    I finally came up with a way to do that. If you're still interested,
    tell me what you think of the following example, which compiles with
    the current version of MinGW's g++ and executes as intended: it
    exposes two errors.

    Regards,
    Richard


    // TemplateErrHandler.c++
    // K:\_Projects\C++\MinGW\04a_TemplateErrHandler\

    #include <string>
    #include <iostream>
    using namespace std;

    template <class T>
    class MyClass {
    public:
    MyClass() {}
    T MyFn()
    {
    /* Invalid attampts:
    return -1029384756; // Error flag
    return "My Message"; // Error flag
    */

    // Correct attempt:
    cout << "ERROR: An error was detected; execution continuing\n";
    T tObj;
    return tOverloaded(tObj);
    }
    private:
    int n;
    int tOverloaded(int val) {return -1029384756;}
    char* tOverloaded(string val){return "My Message";}
    };

    int main ()
    {
    MyClass<int> intInstance;
    cout << "From intInstance: " << intInstance.MyFn() << "\n";

    MyClass<string> strInstance;
    cout << "From strInstance: " << strInstance.MyFn() << "\n";
    }
    RichardOnRails, Oct 30, 2007
    #3
  4. RichardOnRails

    Markus Moll Guest

    Hi

    RichardOnRails wrote:

    > I was using a "toy" application to test alternative error-handling
    > strategies. One was to trap the error, display a msg and exit the app.
    > However, sometimes it's desirable to recover somehow from errors so that
    > additional errors can be exposed in a single pass through all the
    > calls in an app.


    Could you explain what kind of errors you want to detect?

    > I finally came up with a way to do that. If you're still interested,
    > tell me what you think of the following example, which compiles with
    > the current version of MinGW's g++ and executes as intended: it
    > exposes two errors.


    Please explain in more detail what exactly you want to do, because I cannot
    extract it from the example you give (nor from your previous posting...)

    > #include <string>
    > #include <iostream>
    > using namespace std;
    >
    > template <class T>
    > class MyClass {
    > public:
    > MyClass() {}
    > T MyFn()
    > {
    > /* Invalid attampts:
    > return -1029384756; // Error flag
    > return "My Message"; // Error flag
    > */
    >
    > // Correct attempt:
    > cout << "ERROR: An error was detected; execution continuing\n";
    > T tObj;
    > return tOverloaded(tObj);


    Okay... you create a default object tObj of type T. The value you return is
    the return value of another overloaded function, named tOverloaded. This
    return value does not at all depend on tObj (Question: Why do you create
    the object, then?) Furthermore, for types T where no conversion to either
    int or std::string exists, the instantiation of MyClass<T>::MyFn will fail.

    > }
    > private:
    > int n;


    You _never_ use n. Why do you declare it?

    > int tOverloaded(int val) {return -1029384756;}
    > char* tOverloaded(string val){return "My Message";}


    Don't use the string-literal-to-char-pointer conversion. It's only there for
    C-compatibility (string literals are immutable). I think you wanted to
    return string there. Furthermore: Is there _any_ reason why you return "My
    Message" and -1029384756?

    > };
    >
    > int main ()
    > {
    > MyClass<int> intInstance;
    > cout << "From intInstance: " << intInstance.MyFn() << "\n";
    >
    > MyClass<string> strInstance;
    > cout << "From strInstance: " << strInstance.MyFn() << "\n";
    > }


    So you are using MyClass<T> to return some arbitrary T value.

    WHY?

    And why don't you simply use:

    template<typename T> T some_value();
    template<> string some_value<string>() { return "My Message"; }
    template<> int some_value<int>() { return -1029384756; }

    int main()
    {
    cout << "From int: " << some_value<int>() << "\n";
    cout << "From str: " << some_value<string>() << "\n";
    }

    And what does this have to do with error handling and/or exposing two
    errors?

    Markus
    Markus Moll, Oct 30, 2007
    #4
  5. On Oct 30, 9:42 am, Markus Moll <>
    wrote:
    > Hi
    >
    > RichardOnRails wrote:
    > > I was using a "toy" application to test alternative error-handling
    > > strategies. One was to trap the error, display a msg and exit the app.
    > > However, sometimes it's desirable to recover somehow from errors so that
    > > additional errors can be exposed in a single pass through all the
    > > calls in an app.

    >
    > Could you explain what kind of errors you want to detect?
    >
    > > I finally came up with a way to do that. If you're still interested,
    > > tell me what you think of the following example, which compiles with
    > > the current version of MinGW's g++ and executes as intended: it
    > > exposes two errors.

    >
    > Please explain in more detail what exactly you want to do, because I cannot
    > extract it from the example you give (nor from your previous posting...)
    >
    >
    >
    > > #include <string>
    > > #include <iostream>
    > > using namespace std;

    >
    > > template <class T>
    > > class MyClass {
    > > public:
    > > MyClass() {}
    > > T MyFn()
    > > {
    > > /* Invalid attampts:
    > > return -1029384756; // Error flag
    > > return "My Message"; // Error flag
    > > */

    >
    > > // Correct attempt:
    > > cout << "ERROR: An error was detected; execution continuing\n";
    > > T tObj;
    > > return tOverloaded(tObj);

    >
    > Okay... you create a default object tObj of type T. The value you return is
    > the return value of another overloaded function, named tOverloaded. This
    > return value does not at all depend on tObj (Question: Why do you create
    > the object, then?) Furthermore, for types T where no conversion to either
    > int or std::string exists, the instantiation of MyClass<T>::MyFn will fail.
    >
    > > }
    > > private:
    > > int n;

    >
    > You _never_ use n. Why do you declare it?
    >
    > > int tOverloaded(int val) {return -1029384756;}
    > > char* tOverloaded(string val){return "My Message";}

    >
    > Don't use the string-literal-to-char-pointer conversion. It's only there for
    > C-compatibility (string literals are immutable). I think you wanted to
    > return string there. Furthermore: Is there _any_ reason why you return "My
    > Message" and -1029384756?
    >
    > > };

    >
    > > int main ()
    > > {
    > > MyClass<int> intInstance;
    > > cout << "From intInstance: " << intInstance.MyFn() << "\n";

    >
    > > MyClass<string> strInstance;
    > > cout << "From strInstance: " << strInstance.MyFn() << "\n";
    > > }

    >
    > So you are using MyClass<T> to return some arbitrary T value.
    >
    > WHY?
    >
    > And why don't you simply use:
    >
    > template<typename T> T some_value();
    > template<> string some_value<string>() { return "My Message"; }
    > template<> int some_value<int>() { return -1029384756; }
    >
    > int main()
    > {
    > cout << "From int: " << some_value<int>() << "\n";
    > cout << "From str: " << some_value<string>() << "\n";
    >
    > }
    >
    > And what does this have to do with error handling and/or exposing two
    > errors?
    >
    > Markus


    Hi,

    Did you read the original post? I think that explains what I was
    trying to do.

    In Ruby, if I suspected that an object reference I had referred either
    to a string or a number, I could write:

    if obj.responds_to(zero?) puts "obj refers to a number"
    else if obj.responds_to(upcase) puts "obj refers to a string"
    else puts "Who knows what obj refers to?"

    Stoustrup omitted such a capability from C++. I wanted effect such a
    capability, and that's what my example does.

    Maybe the following version will be more illustative.
    --
    Richard


    // TemplateErrHandler.c++
    // K:\_Projects\C++\MinGW\04a_TemplateErrHandler\

    /*TEST RESULTS:
    K:\_Projects\C++\MinGW\04a_TemplateErrHandler>g++ TemplateErrHandler.c
    ++

    K:\_Projects\C++\MinGW\04a_TemplateErrHandler>a
    ERROR: An error was detected; execution continuing
    From intInstance: -1029384756
    ERROR: An error was detected; execution continuing
    From strInstance: My Message

    K:\_Projects\C++\MinGW\04a_TemplateErrHandler>
    */

    #include <string>
    #include <iostream>
    using namespace std;

    template <class T>
    class MyClass {
    public:
    MyClass() {}
    T MyFn()
    {
    /* Invalid attampts:
    return -1029384756; // Error flag
    return "My Message"; // Error flag
    */

    // Correct attempt:
    cout << "ERROR: An error was detected; \n"
    << " execution will continue \n"
    << " by returning an artifical value.\n";
    T tObj;
    return tOverloaded(tObj);
    }
    private:
    int n;
    int tOverloaded(int val) {return -1029384756;}
    char* tOverloaded(string val){return "My Message";}
    };

    int main ()
    {
    MyClass<int> intInstance;
    cout << "Return value from intInstance: " << intInstance.MyFn() << "\n
    \n";

    MyClass<string> strInstance;
    cout << "Return value from strInstance: " << strInstance.MyFn() << "\n
    \n";
    }
    RichardOnRails, Oct 30, 2007
    #5
  6. > private:
    > int n;


    You're right: I never used it. I originally thought I needed it, and
    then forgot to remove it. I've done so now.
    ---
    R.
    RichardOnRails, Oct 30, 2007
    #6
  7. RichardOnRails

    James Kanze Guest

    RichardOnRails wrote:
    > On Oct 30, 1:20 am, Kai-Uwe Bux <> wrote:
    > > RichardOnRails wrote:


    > Your questions/suggestions are well founded. However, I was
    > using a "toy" application to test alternative error-handling
    > strategies. One was to trap the error, display a msg and
    > exit the app. However, sometimes it's desirable to recover
    > somehow from errors so that additional errors can be exposed
    > in a single pass through all the calls in an app.


    There are two standard solutions for this problem, depending on
    the types of errors you're interested in. If the error is
    something "exceptional", i.e. something which won't normally
    occur (like disk full or insufficient memory), you should
    definitely raise an exception. If the error is something
    "normal" (just about any errors in user input, for example), the
    usual solution is to use some variant of the Barton and Nackman
    "Fallible" idiom, perhaps extended to allow additional
    information concerning the error. (There's an implementation
    supporting extended error codes at my site:
    http://kanze.james.neuf.fr/code-en.html, in the Basic
    subsystem.)

    Another, less frequently used idiom is to provide a callback.

    > I finally came up with a way to do that. If you're still
    > interested, tell me what you think of the following example,
    > which compiles with the current version of MinGW's g++ and
    > executes as intended: it exposes two errors.


    It has two major flaws: the calling code doesn't know that there
    was an error, and it outputs error messages to std::cout, which
    is not necessarily where the client code wants them.

    --
    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, Oct 31, 2007
    #7
  8. * James Kanze:
    > RichardOnRails wrote:
    >> On Oct 30, 1:20 am, Kai-Uwe Bux <> wrote:
    >>> RichardOnRails wrote:

    >
    >> Your questions/suggestions are well founded. However, I was
    >> using a "toy" application to test alternative error-handling
    >> strategies. One was to trap the error, display a msg and
    >> exit the app. However, sometimes it's desirable to recover
    >> somehow from errors so that additional errors can be exposed
    >> in a single pass through all the calls in an app.

    >
    > There are two standard solutions for this problem, depending on
    > the types of errors you're interested in. If the error is
    > something "exceptional", i.e. something which won't normally
    > occur (like disk full or insufficient memory), you should
    > definitely raise an exception.


    A newbie should definitely let the program abort, in the case of memory
    exhaustion via a new-handler (set_new_handler or whatever the name was),
    because with basic resource depletion higher level code won't be able to
    do anything and will most likely fail in turn: even the throwing of a
    standard exception might fail... It is perhaps ironic that I have
    argued the position of using exception, e.g. with Dave Abrahams (who
    then took the position I'm doing here, that of terminating at once).
    But that was in the context of very advanced error handling, of possibly
    cleaning up some things and doing a Bird Of Phoenix: error handling for
    newbies and ordinary error handling is something else.


    > If the error is something
    > "normal" (just about any errors in user input, for example), the
    > usual solution is to use some variant of the Barton and Nackman
    > "Fallible" idiom, perhaps extended to allow additional
    > information concerning the error. (There's an implementation
    > supporting extended error codes at my site:
    > http://kanze.james.neuf.fr/code-en.html, in the Basic
    > subsystem.)


    That's good advice, but the advice about choosing exceptions or not
    based on how "exceptional" the situation is IMO ungood advice -- no
    matter that it is advice that's (mindlessly, and with reference to some
    "authority") repeated by a majority of C++ programmers.

    In addition to being so vague and subjective as to be worthless, it's
    worthless because what can be "exceptional" in one context need not be
    exceptional in some other context.

    Instead, use exceptions where they provide clarity and are most
    practical -- same advice as for use of loop constructs and other
    language constructs.


    Cheers,

    - Alf


    --
    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?
    Alf P. Steinbach, Oct 31, 2007
    #8
  9. RichardOnRails

    Joe Greer Guest

    "Alf P. Steinbach" <> wrote in news::

    >> subsystem.)

    >
    > That's good advice, but the advice about choosing exceptions or not
    > based on how "exceptional" the situation is IMO ungood advice -- no
    > matter that it is advice that's (mindlessly, and with reference to some
    > "authority") repeated by a majority of C++ programmers.
    >
    > In addition to being so vague and subjective as to be worthless, it's
    > worthless because what can be "exceptional" in one context need not be
    > exceptional in some other context.
    >
    > Instead, use exceptions where they provide clarity and are most
    > practical -- same advice as for use of loop constructs and other
    > language constructs.
    >
    >



    I like the rule of thumb given on the boost site. Use exceptions if what you want is
    stack unwinding, otherwise use an error code. In other words, if you generally expect
    the immediate caller to handle the error in some way, don't use exceptions. If you
    expect the error to be handled at a higher level than the immediate caller, then an
    exception might well be the way to go.

    joe
    Joe Greer, Oct 31, 2007
    #9
  10. On Oct 31, 11:37 am, Joe Greer <> wrote:
    > "Alf P. Steinbach" <> wrote innews::
    >
    >
    >
    > >> subsystem.)

    >
    > > That's good advice, but the advice about choosing exceptions or not
    > > based on how "exceptional" the situation is IMO ungood advice -- no
    > > matter that it is advice that's (mindlessly, and with reference to some
    > > "authority") repeated by a majority of C++ programmers.

    >
    > > In addition to being so vague and subjective as to be worthless, it's
    > > worthless because what can be "exceptional" in one context need not be
    > > exceptional in some other context.

    >
    > > Instead, use exceptions where they provide clarity and are most
    > > practical -- same advice as for use of loop constructs and other
    > > language constructs.

    >
    > I like the rule of thumb given on the boost site. Use exceptions if what you want is
    > stack unwinding, otherwise use an error code. In other words, if you generally expect
    > the immediate caller to handle the error in some way, don't use exceptions. If you
    > expect the error to be handled at a higher level than the immediate caller, then an
    > exception might well be the way to go.
    >
    > joe


    Hey guys, thanks for your additional ideas. I was just playing around
    with a stack implementation I downloaded because I hadn't written any C
    ++ since I retired 6 years ago. Because it was using it merely as a
    toy I added rudimentary error handling with messages directed to
    stdout with immediate exit thereafter.

    Then I thought I should play with the idea of adding a boolean DEBUG
    symbol to allow reporting multiple error in a single session.
    However, allowing continued execution after issuing an error message
    proved problematical when the offending method's definition specified
    a templated return type.

    In the latter case, I had to be conjure a suitable dummy return
    value. And that value had to be a literal of of the templated type.
    I had in mind the ease with which I could that in Ruby, which is rich
    in metaprogramming facilities. But nothing came to mind for C++.
    Hence the post.

    Then the idea of creating overload methods came to me and I was a
    happy campler. So I'm signing off from this thread with thanks to all
    respondents. I will keep your ideas in mind if I ever do serious C++
    programming again.
    --
    Richard
    RichardOnRails, Nov 1, 2007
    #10
  11. RichardOnRails

    James Kanze Guest

    On Oct 31, 3:40 pm, "Alf P. Steinbach" <> wrote:
    > * James Kanze:
    > > RichardOnRails wrote:
    > >> On Oct 30, 1:20 am, Kai-Uwe Bux <> wrote:
    > >>> RichardOnRails wrote:


    > >> Your questions/suggestions are well founded. However, I was
    > >> using a "toy" application to test alternative error-handling
    > >> strategies. One was to trap the error, display a msg and
    > >> exit the app. However, sometimes it's desirable to recover
    > >> somehow from errors so that additional errors can be exposed
    > >> in a single pass through all the calls in an app.


    > > There are two standard solutions for this problem, depending on
    > > the types of errors you're interested in. If the error is
    > > something "exceptional", i.e. something which won't normally
    > > occur (like disk full or insufficient memory), you should
    > > definitely raise an exception.


    > A newbie should definitely let the program abort,


    Probably. (If the newbie is working in a larger team, he should
    use whatever mechanisms the team has established. But setting
    up a framework to do anything but abort isn't a task for a
    newbie.)

    Running out of memory just happens to be a convenient example.
    More generally, of course, you have a complete hierarchy of ways
    to handle errors, from aborting, to simply noting the error and
    continuing in a degraded mode (something like ostream, for
    example). Which one to use will depend on the type of error and
    the application constraits. There is no universally "right"
    solution. Which is really what lies at the heart of the
    original question: if you're writing a generic class, for use in
    many different applications, what do you do? The most useful
    solution is generally to use the least radical solution which
    could reasonably apply. In the case of out of memory, it's hard
    to imagine anything less that an exception as being acceptable,
    although I agree that at least 90% of the time (newbie or not),
    aborting is what is really required. But from the user's point
    of view, it's easier to convert an exception into an
    abort---just don't catch it:)---than it is to convert an abort
    into an exception.

    > in the case of memory exhaustion via a new-handler
    > (set_new_handler or whatever the name was), because with basic
    > resource depletion higher level code won't be able to do
    > anything and will most likely fail in turn: even the throwing
    > of a standard exception might fail...


    Formally, just about anything might fail at any time. The
    standard has a cop out saying that not enough resources is
    undefined behavior. Of course, we all count on quality of
    implementation as well. On the systems I use, you can catch
    bad_alloc and continue (although you may have to configure the
    OS correctly in order for the error to be detected). On the
    systems I use, there are even ways of guaranteeing that the
    stack doesn't overflow (but they're very system dependent).

    > It is perhaps ironic that I have argued the position of using
    > exception, e.g. with Dave Abrahams (who then took the position
    > I'm doing here, that of terminating at once). But that was in
    > the context of very advanced error handling, of possibly
    > cleaning up some things and doing a Bird Of Phoenix: error
    > handling for newbies and ordinary error handling is something
    > else.


    It all depends on the application. I write large scale server
    software. My programs run on dedicated machines, with
    sufficient memory. Most of the time, if I run out of memory,
    the only possible reason could be a memory leak. In that case,
    it's definitly best to abort and restart the application; the
    situation won't get any better otherwise. But there are
    exceptions: consider a protocol like LDAP, where the client can
    send arbitrary "expressions", which will typically be
    represented internally in the form of an expression graph.
    Regardless of how much memory you have, expressions which
    require more can exist. In such case, catching bad_alloc and
    responding with an "insufficient resources" error is a very
    viable solution. (If you've programmed correctly, the stack
    walkback of the exception will ensure that all of the nodes are
    released.)

    > > If the error is something
    > > "normal" (just about any errors in user input, for example), the
    > > usual solution is to use some variant of the Barton and Nackman
    > > "Fallible" idiom, perhaps extended to allow additional
    > > information concerning the error. (There's an implementation
    > > supporting extended error codes at my site:
    > >http://kanze.james.neuf.fr/code-en.html, in the Basic
    > > subsystem.)


    > That's good advice, but the advice about choosing exceptions
    > or not based on how "exceptional" the situation is IMO ungood
    > advice -- no matter that it is advice that's (mindlessly,
    > and with reference to some "authority") repeated by a majority
    > of C++ programmers.


    > In addition to being so vague and subjective as to be
    > worthless, it's worthless because what can be "exceptional" in
    > one context need not be exceptional in some other context.


    It's vague and subjective precisely because it depends on the
    context. No one is claiming anything else. It's a sort of way
    of saying that it depends, with a very vague suggestion about
    what might be relevant to consider.

    > Instead, use exceptions where they provide clarity and are
    > most practical -- same advice as for use of loop constructs
    > and other language constructs.


    OK. I'm not sure what "most practical" really means in this
    context, but clarity is certainly important. Of course, which
    solution is clearest will also depend on the application:
    "provides clarity and are most pratical" is also vague and
    subjective.

    Which is fine, because the issue is vague and subjective; since
    the correct answer depends a lot on context, any context free
    answer must be vague and subjective.

    --
    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, Nov 2, 2007
    #11
  12. RichardOnRails

    James Kanze Guest

    On Oct 31, 4:37 pm, Joe Greer <> wrote:
    > "Alf P. Steinbach" <> wrote
    > innews::


    > > That's good advice, but the advice about choosing exceptions
    > > or not based on how "exceptional" the situation is IMO
    > > ungood advice -- no matter that it is advice that's
    > > (mindlessly, and with reference to some "authority")
    > > repeated by a majority of C++ programmers.


    > > In addition to being so vague and subjective as to be
    > > worthless, it's worthless because what can be "exceptional"
    > > in one context need not be exceptional in some other
    > > context.


    > > Instead, use exceptions where they provide clarity and are
    > > most practical -- same advice as for use of loop
    > > constructs and other language constructs.


    > I like the rule of thumb given on the boost site. Use
    > exceptions if what you want is stack unwinding, otherwise use
    > an error code. In other words, if you generally expect the
    > immediate caller to handle the error in some way, don't use
    > exceptions. If you expect the error to be handled at a higher
    > level than the immediate caller, then an exception might well
    > be the way to go.


    That's the general idea, but it also begs the question. If
    you're writing a generic class, used in many different contexts,
    how do you know which is which?

    There are many different strategies for handling errors, in
    order of gravity: abort, exception, return code, and internal
    status with a degraded mode of operation. (There are others,
    but they are either rare, or should be.) As a general rule, if
    you're in doubt, you should use the weakest method: in
    particular, library code should never abort except in response
    to a programming error (assertion failure), and should prefer a
    return code to an exception if there's any reasonable chance of
    the error being handled "locally". The cases where internal
    state and degraded operation are rarer, but two of them are very
    widespread: IO and floating point arithmetic.

    --
    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, Nov 2, 2007
    #12
    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. RA Scheltema
    Replies:
    3
    Views:
    379
    RA Scheltema
    Jan 6, 2004
  2. Marijn
    Replies:
    5
    Views:
    437
    Marijn
    Feb 13, 2004
  3. Replies:
    0
    Views:
    2,211
  4. Amadeus W. M.
    Replies:
    2
    Views:
    380
    Amadeus W. M.
    Jul 4, 2006
  5. Replies:
    1
    Views:
    291
Loading...

Share This Page