4
\$\begingroup\$

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 <exception>
#include <string>
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<< (char* s)
 {
 whatStr.append(s);
 return *this;
 }
 failure& operator<< (char const* s)
 {
 whatStr.append(s);
 return *this;
 }
 failure& operator<< (::std::string const& s)
 {
 whatStr.append(s);
 return *this;
 }
 template <class T>
 failure& operator<< (T const& val)
 {
 whatStr.append(::std::to_string(val));
 return *this;
 }
};
class eof : public failure {
public:
 explicit eof (char const* what_) : failure(what_)
 {}
 ~eof () throw()
 {}
 template <class T>
 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.

asked Sep 17, 2013 at 2:53
\$\endgroup\$
6
  • 1
    \$\begingroup\$ Is this code from your archive, or someone else's? \$\endgroup\$ Commented Sep 17, 2013 at 2:56
  • \$\begingroup\$ @Jamal It's part of my archive. \$\endgroup\$ Commented Sep 17, 2013 at 3:21
  • \$\begingroup\$ Okay, just making sure. \$\endgroup\$ Commented Sep 17, 2013 at 3:26
  • \$\begingroup\$ I think there's a typo for the std::to_string(). The :: in front of it shouldn't be there. \$\endgroup\$ Commented Sep 17, 2013 at 20:37
  • 1
    \$\begingroup\$ If you inherit form std::exception then you can put the break point in std::exception::exception that's a nice central place to catch exceptions. \$\endgroup\$ Commented Sep 17, 2013 at 22:09

1 Answer 1

4
\$\begingroup\$

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");
answered Sep 17, 2013 at 9:31
\$\endgroup\$
1
  • \$\begingroup\$ I edited the original post. Am adding a comment here because I'm not sure you'll be notified otherwise. \$\endgroup\$ Commented Sep 17, 2013 at 19:57

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.