[ create a new paste ] login | about

Link: http://codepad.org/XYZwZGWO    [ raw code | fork ]

mloskot - C++, pasted on Jan 14:
// Sample: sink all exceptions in one place and translate to return code
// Author: Mateusz Loskot <mateusz at loskot dot net>
#include <cassert>
#include <exception>
#include <iostream>
#include <stdexcept>

template <typename T>
inline T const& handle_exception(char const* const who, T const& rc)
{
    try
    {
        throw;
    }
    catch (int e)
    {
        std::cerr << who << " caught int: " << e << std::endl;
    }
    catch (char const* e)
    {
        std::cerr << who << " caught c-string: " << e << std::endl;
    }
    catch (std::exception const& e)
    {
        std::cerr << who << " caught std::exception: " << e.what() << std::endl;
    }
    return rc;
}

#define EXCEPTION_TRY() \
    try {

#define EXCEPTION_CATCH_AND_RETURN(success, failure) \
    } catch (...) { \
        return handle_exception(__FUNCTION__, failure); \
    } \
    return success;

#define EXCEPTION_CATCH_AND_EXIT() \
    } catch (...) { handle_exception(__FUNCTION__, false); return; }

template <typename T>
class number
{
public:

    // public ctor, may throw
    number(T value) : value_(value)
    {
        if (value != value)
            throw "value is NaN";
    }

    // public save division, never throws, 
    bool divide_s(double& result, T const& den) const
    {
        EXCEPTION_TRY()
        result = divide_(value_, den);
        EXCEPTION_CATCH_AND_RETURN(true, false)
    }

private:
    T value_;

    // used internally by other private methods, allowed to throw
    double divide_(T const& num, T const& den) const
    {
        if (den > 0)
        {
            return num / den;
        }
        throw std::invalid_argument("denominator is zero");
    }
};

// C wrapper is not allowed to throw exceptions
double divide_numbers(double num, double den)
{
    EXCEPTION_TRY()
    
    number<double> n(num);
    double r = 0;
    n.divide_s(r, den);

    EXCEPTION_CATCH_AND_RETURN(true, false)
}

int main()
{
    bool success(false);
    double result(0);

    // Using C++ interface
    {
        number<int> n(10);

        // no error logged
        success = n.divide_s(result, 2);
        assert(success);

        // error logged, flag returned
        success = n.divide_s(result, 0);
        assert(!success);
    }

    // Using C interface
    {
        // no error logged
        result = divide_numbers(10, 2);
        
        // error logged
        result = divide_numbers(10, 0);

        // error logged
        float nan = 0;
        result = divide_numbers(nan / 0, 10);
    }
    
}


Create a new paste based on this one


Comments: