Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Reworking exception class

18 views
Skip to first unread message

woodb...@gmail.com

unread,
Dec 23, 2016, 3:13:22 PM12/23/16
to
I've posted this class here previously and am thinking about
it again.

#pragma once

#include <exception>
#include <string>
#include <experimental/string_view>
#include <utility> // move

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

public:
explicit failure (char const* w):whatStr(w) {}
explicit failure (::std::string& w):whatStr(::std::move(w)) {}

explicit failure (char const* w, int tot) {
if(tot>0)whatStr.reserve(tot);
whatStr=w;
}

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

failure& operator<< (::std::string const& s)
{
whatStr.append(s);
return *this;
}

failure& operator<< (char* s)
{
whatStr.append(s);
return *this;
}

failure& operator<< (char const* s);
failure& operator<< (int i);

template <class T>
failure& operator<< (T val)
{
using ::std::to_string;
return *this<<to_string(val);
}
};
}

I've noticed how the constructors and numerous operator<<
implementations are just wrapping std::string functionality.
One idea to try to get rid of the operator<<'s is to add a
variadic constructor to the class. I think I could use
is_arithmetic or is_numeric or something like that to
figure out if I need to convert an argument to a string.

And I run into some trouble with std::string_view

failure& operator<< (::std::experimental::string_view const& s)
{
whatStr.append(s.data(),s.size());
return *this;
}

I can't just call append() and give a string_view. So is
there a way to figure out if an argument is a string_view?
I'm using clang++ 3.8.1. I've been told in newer compilers it
will be possible to pass a string_view to std::string;;append.
But not sure what to do at this time when I don't have support
for that. Anyway, does this sound like a good change to make
to this class? Thanks in advance.


Brian
Ebenezer Enterprises - "Oh, come, all ye faithful,
Joyful and triumphant! Oh, come ye, oh, come ye to Bethlehem."

http://webEbenezer.net

Daniel

unread,
Dec 23, 2016, 4:00:38 PM12/23/16
to
On Friday, December 23, 2016 at 3:13:22 PM UTC-5, woodb...@gmail.com wrote:
>
> ::std::exception

The leading :: is annoying

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

Here you're overriding a virtual function, so you should write it as

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

> explicit failure (::std::string& w):whatStr(::std::move(w)) {}

That will still give you a copy construction. Perhaps you meant

explicit failure (std::string&& w):whatStr(std::forward<std::string&&>(w)) {}

> explicit failure (char const* w, int tot) {
> if(tot>0)whatStr.reserve(tot);
> whatStr=w;
> }

That is going to be less efficient than simply

explicit failure (char const* w, int tot)
: whatStr(w,tot)
{
}
>
> failure& operator<< (::std::string const& s)
> {
> whatStr.append(s);
> return *this;
> }
>
> failure& operator<< (char* s)
> {
> whatStr.append(s);
> return *this;
> }
>
> failure& operator<< (char const* s);
> failure& operator<< (int i);
>
> template <class T>
> failure& operator<< (T val)
> {
> using ::std::to_string;
> return *this<<to_string(val);
> }

I don't think appending to whatStr like this is a good idea. For one thing, it
doesn't accommodate internationalization. Use string formats, look them up
based on error codes, and substitute placement values.

> figure out if I need to convert an argument to a string.
>
> And I run into some trouble with std::string_view
>
> failure& operator<< (::std::experimental::string_view const& s)
> {
> whatStr.append(s.data(),s.size());
> return *this;
> }
>

I believe the experimental std:string_view has an explicit conversion operator
to std::string, so you should be able to use static_cast.

Daniel

Chris Vine

unread,
Dec 24, 2016, 11:44:32 AM12/24/16
to
On Fri, 23 Dec 2016 13:00:28 -0800 (PST)
Daniel <daniel...@gmail.com> wrote:
> On Friday, December 23, 2016 at 3:13:22 PM UTC-5, woodb...@gmail.com
> wrote:
> >
> > ::std::exception
>
> The leading :: is annoying

As is the gratuitous removal of whitespace in his code.

> > char const* what () const throw() { return whatStr.c_str(); }
>
> Here you're overriding a virtual function, so you should write it as
>
> const char* what() const noexcept override { return
> whatStr.c_str(); }
>
> > explicit failure (::std::string& w):whatStr(::std::move(w)) {}
>
> That will still give you a copy construction. Perhaps you meant
>
> explicit failure (std::string&&
> w):whatStr(std::forward<std::string&&>(w)) {}

His copy constructor is certainly highly broken because with his version
of it he can bind neither an rvalue nor a const lvalue to it. However,
assuming he wants a move constructor, this would be a more obvious, or at
least shorter, way of doing it:

explicit failure (std::string&& w): whatStr(std::move(w)) {}

Chris
0 new messages