HiveBrain v1.2.0
Get Started
← Back to all entries
debugcppMinor

Exception classes

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
classesexceptionstackoverflow

Problem

This code can be found in the archive here. Usually I have a .cc file, but in this case it's all in a header. Am wondering about that. It needs to work in VS12. If possible I'll post more code from the archive for review. I started with this because it's used a lot. Tia.

#ifndef CMW_ErrorWords_hh
#define CMW_ErrorWords_hh

#include 
#include 

namespace cmw {
class failure : public ::std::exception {
  ::std::string whatStr;

public:
  explicit failure (char const* what_) : whatStr(what_)
  {}

  explicit failure (::std::string what_) : whatStr(::std::move(what_))
  {}

  ~failure () throw()
  {}

  char const* what () const throw()
  { return whatStr.c_str(); }

  failure& operator
  failure& operator
  eof& operator<< (T val)
  {
    failure::operator<<(val);
    return *this;
  }
};

}
#endif


Edit - @Loki Astari

I have compile problems on both clang and gcc if I remove the non const version of that function. Clang says there's "no matching function for call to to_string."

whatStr.append(::std::to_string(val));


IIuc it goes on to say it doesn't like this line:

raise(failure("Blah blah  ") << yytext);


I ran across that a few months ago and found that adding the non-const version got the compilers to accept it. I'm not sure what the problem is really. I'm using flex and that's where yytext comes from.

Oo Tiib suggested the raise function as a help for debugging -- a central function where you could put a breakpoint to see the stack. It may be something used in some large projects. That made some sense so I decided to try it. I believe I need both versions of raise to avoid slicing.

Edit 2:

Removed raise functions from above code.

Solution

Though std::exception does not have a constructor for taking an error message; the other standard excretions do. So you can make your exception class simpler by inheriting from one of these.

class failure : public ::std::runtime_error {

    public:
       failure (std::string const& msg) : ::std::runtime_error(msg)


I understand you are trying to make your exceptions easier to use by adding a couple of stream operator to the class. But you can achieve the same affect with greater flexibility using std::stringstream.

// Your way:
 failure x("Hi there");
 x << ": More info:" << 5 << " At night:" << 22;

 // using string stream (works with all stream-able types)
 std::stringstream msg;
 msg << "Hi there" << ": More info:" << 5 << " At night:" << 22;
 failure y(msg.str());


If the only difference between a methods is the constness of their parameters. Then the const version is all you need. As it will accept normal values and promise not to change them.

// This method is not needed
failure& operator<< (char* s)
{
    whatStr.append(s);
    return *this;
}

// This method will handle both
// `char*` and `char const*` perfectly well.
// if you remove the first method above.
failure& operator<< (char const* s)
{
    whatStr.append(s);
    return *this;
}


I don't like your raise (and why two different version. Why not raise on the base class of std::exception (that will cover you for all exceptions)).

inline void raise (failure const& ex)


In my opinion (so its perfectly valid to believe differently) this buys you nothing and makes the code less readable.

raise(failure("hi"));

// Vs

throw failure("Hi");

Code Snippets

class failure : public ::std::runtime_error {

    public:
       failure (std::string const& msg) : ::std::runtime_error(msg)
// Your way:
 failure x("Hi there");
 x << ": More info:" << 5 << " At night:" << 22;

 // using string stream (works with all stream-able types)
 std::stringstream msg;
 msg << "Hi there" << ": More info:" << 5 << " At night:" << 22;
 failure y(msg.str());
// This method is not needed
failure& operator<< (char* s)
{
    whatStr.append(s);
    return *this;
}

// This method will handle both
// `char*` and `char const*` perfectly well.
// if you remove the first method above.
failure& operator<< (char const* s)
{
    whatStr.append(s);
    return *this;
}
inline void raise (failure const& ex)
raise(failure("hi"));

// Vs

throw failure("Hi");

Context

StackExchange Code Review Q#31404, answer score: 4

Revisions (0)

No revisions yet.