Thread: Run-time function identification

  1. #1
    Registered User
    Join Date
    Mar 2016
    Posts
    203

    Run-time function identification

    Two functions, hmean() and gmean(), either of which can throw exceptions that are caught in the same catch block. How can I identify which of the 2 functions has thrown the exception while continuing to use a single catch block? Code below:

    Code:
    #include<iostream>
    #include<stdexcept>
    #include<cmath>
    using namespace std;
    class exp_catch: public logic_error{
        public:
            exp_catch(double x, double y, const char *s = "Logic error exception thrown!!!"):m_x(x), m_y(y), logic_error(s){}
            void hmean() throw(logic_error);
            void gmean() throw (logic_error);
            void show_val();
        private:
            double m_x;
            double m_y;    
    };
    int main(){
        exp_catch e1(10, -12);
        try{
        e1.hmean();
        e1.gmean();
        }
        catch(logic_error & le){
            cout<<le.what()<<endl;
            e1.show_val();
        }
    }
    void exp_catch::hmean() throw (logic_error){
        if(m_x == -m_y){
            throw *this;
        }
        double z = (2 * m_x * m_y) /(m_x + m_y);
        cout <<"Harmonic mean is: "<<z<<endl;
    }
    void exp_catch::gmean() throw(logic_error){
        if (m_x < 0 || m_y < 0){
            throw *this;
        }
        double z = std::sqrt(m_x * m_y);
        cout<<"Geometric mean is: "<< z<<endl;
    }
    void exp_catch::show_val(){
        cout<<"The input values are: "<<m_x<<" and "<<m_y<<endl;
    }
    Thank you

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    Maybe?
    Code:
    #include<iostream>
    #include<stdexcept>
    #include<cmath>
    using namespace std;
    class exp_catch: public logic_error{
    public:
      exp_catch(double x, double y, const char *s = "Logic error exception thrown!!!"):m_x(x), m_y(y), logic_error(s){}
      void hmean() throw(logic_error);
      void gmean() throw (logic_error);
      void show_val();
    private:
      double m_x;
      double m_y;    
      const char *m_lastfn;
    };
    int main(){
      exp_catch e1(10, -12);
      try{
        e1.hmean();
        e1.gmean();
      }
      catch(logic_error & le){
        cout<<le.what()<<endl;
        e1.show_val();
      }
    }
    void exp_catch::hmean() throw (logic_error){
      m_lastfn = __PRETTY_FUNCTION__;
      if(m_x == -m_y){
        throw *this;
      }
      double z = (2 * m_x * m_y) /(m_x + m_y);
      cout <<"Harmonic mean is: "<<z<<endl;
    }
    void exp_catch::gmean() throw(logic_error){
      m_lastfn = __PRETTY_FUNCTION__;
      if (m_x < 0 || m_y < 0){
        throw *this;
      }
      double z = std::sqrt(m_x * m_y);
      cout<<"Geometric mean is: "<< z<<endl;
    }
    void exp_catch::show_val(){
      cout<<"The input values are: "<<m_x<<" and "<<m_y<<endl;
      cout<<"Occurred in " << m_lastfn << endl;
    }
    
    
    $ g++  foo.cpp
    $ ./a.out 
    Harmonic mean is: 120
    Logic error exception thrown!!!
    The input values are: 10 and -12
    Occurred in void exp_catch::gmean()
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    Mar 2016
    Posts
    203
    Thank you very much indeed for pointing me in the general direction of __PRETTY_FUNCTION__, __FUNCTION__, __func__ and then I can see that there are similar macros for LINE, FILE etc. I was not aware of this part of C++ and am very grateful for your help. Regards,

  4. #4
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    You should have a member in your class that identifies exactly what kind of error occurred. Then from what, you can determine where the error occurred. But really, you shouldn't so much pay attention to where it came from as much as what kind of error it was.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  5. #5
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    Quote Originally Posted by Elysia
    You should have a member in your class that identifies exactly what kind of error occurred.
    I thought that's why exceptions were typed.
    Quote Originally Posted by Elysia
    But really, you shouldn't so much pay attention to where it came from as much as what kind of error it was.
    That seems like really stupid advice, since in the code given the only way to prevent the exception is to pass good arguments... it makes sense you would need to know the offending function call. Every backtrace I've ever seen keeps track of line, file and function name so it is need to know information.

    Quote Originally Posted by sean_cantab
    Two functions, hmean() and gmean(), either of which can throw exceptions that are caught in the same catch block.
    You really should extract gmean and hmean from the exception class.

  6. #6
    Registered User
    Join Date
    Mar 2016
    Posts
    203
    Quote Originally Posted by whiteflags View Post
    You really should extract gmean and hmean from the exception class.
    Yes, thanks, that was done as part of another exercise.

  7. #7
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by whiteflags View Post
    I thought that's why exceptions were typed.
    Not necessarily always. You can use enums and other information bundled in the exception to specify more information. Many libraries tend to group exceptions into different categories and using constants or whatever to give more detailed information.

    That seems like really stupid advice, since in the code given the only way to prevent the exception is to pass good arguments... it makes sense you would need to know the offending function call. Every backtrace I've ever seen keeps track of line, file and function name so it is need to know information.
    It paves way for abstraction, which is a good thing™. How many functions do you have in your application? Are you going to try to use different error parsing for every function? What if your functions change? What if they're refactored? Besides, many functions can throw many errors.

    Backtraces are good, but they're not meant for users. They're meant for developers to help track down the error. That information shouldn't be used by the code to determine where the error came from.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  8. #8
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    OK ... I'm not asking you to justify specific error handling designs to me. I am already aware that exceptions can be hierarchies, use explanatory constants, etc. What confused me about what you said about not needing to know where the error occurred.

    Then from what, you can determine where the error occurred. But really, you shouldn't so much pay attention to where it came from as much as what kind of error it was.
    Right, but what information would the string have if we're not supposed to care where the error occurred?

    I mean, I don't expect what to be a full backtrace, but I do expect it to have information typical of one - function name, line, file... hopefully it is clear what I am asking because I don't know where you are going with your advice.
    Last edited by whiteflags; 06-16-2016 at 06:46 AM.

  9. #9
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    I believe we're on the same track. I do believe having information about where the error came from to be useful. But I don't think the code should act on it. It's the developer's job to act on it:

    Code:
    catch (MyEx ex) // Being lazy
    {
        switch (ex.Error) // Determine what kind of error happened and try to recover; or present an error to the user.
        {
            // ...
        }
        Log(ex.Backtrace); // Log the backtrace so the developer can see exactly why the error occurred.
    }
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Variable Identification
    By sphinxsquare in forum C Programming
    Replies: 4
    Last Post: 04-22-2012, 04:57 PM
  2. Fingerprint identification project
    By deeptikoshy in forum C Programming
    Replies: 1
    Last Post: 04-12-2012, 06:03 AM
  3. Process Identification
    By pjdriverdude in forum C Programming
    Replies: 4
    Last Post: 09-11-2009, 10:33 AM
  4. runtime type identification
    By nads20489 in forum C Programming
    Replies: 6
    Last Post: 07-22-2009, 11:48 AM
  5. speech identification
    By subdene in forum A Brief History of Cprogramming.com
    Replies: 6
    Last Post: 01-08-2005, 12:56 PM

Tags for this Thread