f



Reworking exception class

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
0
woodbrian77
12/23/2016 8:13:14 PM
comp.lang.c++ 49423 articles. 6 followers. Post Follow

2 Replies
512 Views

Similar Articles

[PageSpeed] 13

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
0
Daniel
12/23/2016 9:00:28 PM
On Fri, 23 Dec 2016 13:00:28 -0800 (PST)
Daniel <danielaparker@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
Chris
12/24/2016 4:44:20 PM
Reply: