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

Adding a function to std::exception and company

125 views
Skip to first unread message

woodb...@gmail.com

unread,
Jan 25, 2017, 12:58:34 PM1/25/17
to
I'd like to see something like this added to std::exception
and types derived from it:

virtual ::std::string_view what_view () const noexcept;

In this file:

https://github.com/Ebenezer-group/onwards/blob/master/cmwAmbassador.cc

there's some code like this:

}catch(::std::exception const& ex){
syslog_wrapper(LOG_ERR,"Mediate request: %s",ex.what());
middle_messages_front::Marshal(localsendbuf,false,ex.what());
}

I can't change the first call to "what" unless I find an alternative to
syslog. But I could change the second call to "what" to "what_view"
and avoid the need to recalculate the length of the string.

The proposed function could be implemented like this:

virtual ::std::string_view what_view () const noexcept
{ return std::string_view(whatStr); } // where whatStr is a std::string.

At least that's how I would do it here:
https://github.com/Ebenezer-group/onwards/blob/master/ErrorWords.hh

I'm not planning on going to the upcoming C++ standardization
meeting in Kona, Hawii, but if someone is, feel free to mention
this. Thanks.


Brian
Ebenezer Enterprises - In G-d we trust.
http://webEbenezer.net

Alf P. Steinbach

unread,
Jan 25, 2017, 2:18:37 PM1/25/17
to
On 25.01.2017 18:58, woodb...@gmail.com wrote:
> I'd like to see something like this added to std::exception
> and types derived from it:
>
> virtual ::std::string_view what_view () const noexcept;
>
> In this file:
>
> https://github.com/Ebenezer-group/onwards/blob/master/cmwAmbassador.cc
>
> there's some code like this:
>
> }catch(::std::exception const& ex){
> syslog_wrapper(LOG_ERR,"Mediate request: %s",ex.what());
> middle_messages_front::Marshal(localsendbuf,false,ex.what());
> }
>
> I can't change the first call to "what" unless I find an alternative to
> syslog. But I could change the second call to "what" to "what_view"
> and avoid the need to recalculate the length of the string.

If you create your own exception class you can provide a method that
returns a string view, to avoid copying of the string.

Think also about creating an exception instance from a string view.

One doesn't want conversion to `std::string` there because that can throw.


> The proposed function could be implemented like this:
>
> virtual ::std::string_view what_view () const noexcept
> { return std::string_view(whatStr); } // where whatStr is a std::string.
>
> At least that's how I would do it here:
> https://github.com/Ebenezer-group/onwards/blob/master/ErrorWords.hh
>
> I'm not planning on going to the upcoming C++ standardization
> meeting in Kona, Hawii, but if someone is, feel free to mention
> this. Thanks.

Just a side note: exceptions and strings have a circular dependency
relationship, which makes it difficult to implement it all in header
only modules.


Cheers!,

- Alf

woodb...@gmail.com

unread,
Jan 25, 2017, 10:15:21 PM1/25/17
to
On Wednesday, January 25, 2017 at 1:18:37 PM UTC-6, Alf P. Steinbach wrote:
> On 25.01.2017 18:58, woodb...@gmail.com wrote:
> > I'd like to see something like this added to std::exception
> > and types derived from it:
> >
> > virtual ::std::string_view what_view () const noexcept;
> >
> > In this file:
> >
> > https://github.com/Ebenezer-group/onwards/blob/master/cmwAmbassador.cc
> >
> > there's some code like this:
> >
> > }catch(::std::exception const& ex){
> > syslog_wrapper(LOG_ERR,"Mediate request: %s",ex.what());
> > middle_messages_front::Marshal(localsendbuf,false,ex.what());
> > }
> >
> > I can't change the first call to "what" unless I find an alternative to
> > syslog. But I could change the second call to "what" to "what_view"
> > and avoid the need to recalculate the length of the string.
>
> If you create your own exception class you can provide a method that
> returns a string view, to avoid copying of the string.

I tried that but ran into a problem when I catch exceptions
using std::exception. I don't really want to have to have
an additional catch block (in various places) for my exceptions.

>
> Think also about creating an exception instance from a string view.
>
> One doesn't want conversion to `std::string` there because that can throw.
>

I'm not sure if you mean to use string_view in the implementation
or in the class/constructor interface. I've thought about using it
in the interface, but haven't gotten there yet. Thank you for your
comments.


Brian

woodb...@gmail.com

unread,
Jan 27, 2017, 3:02:43 PM1/27/17
to
I changed a constructor in that class to take a string_view:

https://github.com/Ebenezer-group/onwards/blob/master/ErrorWords.hh

. Now I'm wondering if anyone has written a composite type trait --
something like is_stringy -- that returns true if T is a std::string,
std::string_view, char*, or char const*. I have these 4 functions:

failure& operator<< (::std::string const& s);
failure& operator<< (::std::string_view const& s);
failure& operator<< (char* s);
failure& operator<< (char const* s);

that all have the same implementation. An is_stringy would help
me clean that up. With the advent of string_view, it's a good
reminder to do something about this.



Brian
Ebenezer Enterprises - 7 days without prayer makes one weak.
http://webEbenezer.net

Christopher J. Pisz

unread,
Jan 27, 2017, 3:42:12 PM1/27/17
to
what's this C++17 stuff? I dunno what a string view is yet, as opposed
to a string. Either, way, what's wrong with the char * you get now? When
I derive from a std::exception, I can just constuct my string when I
need it, and who cares about the copy? It's an exception, which should
occur exceptionally.

woodb...@gmail.com

unread,
Jan 27, 2017, 4:18:20 PM1/27/17
to
Why pay for what you don't need?
If you have a std::string, and a lot of people do, you can avoid
throwing away the length by using string_view rather than char*.


> When
> I derive from a std::exception, I can just constuct my string when I
> need it, and who cares about the copy? It's an exception, which should
> occur exceptionally.

The faster you handle an exception, the sooner you will be
able to encounter the next one.


Brian
Ebenezer Enterprises - "No man ever listened himself out of a job."
Calvin Coolidge

http://webEbenezer.net

Ian Collins

unread,
Jan 27, 2017, 4:37:50 PM1/27/17
to
On 01/28/17 09:42 AM, Christopher J. Pisz wrote:

> what's this C++17 stuff? I dunno what a string view is yet, as opposed
> to a string. Either, way, what's wrong with the char * you get now? When
> I derive from a std::exception, I can just constuct my string when I
> need it, and who cares about the copy? It's an exception, which should
> occur exceptionally.

Indeed. The cost of throwing far outweighs the cost of generating a string.

--
Ian

Bo Persson

unread,
Jan 28, 2017, 6:17:24 AM1/28/17
to
On the other hand, there are lots of exception classes - like the
standard ones - that don't store an std::string. Like

const char* bad_cast::what() const noexcept
{ return "bad cast"; }


Adding to its interface will be an added cost.


Bo Persson


woodb...@gmail.com

unread,
Jan 28, 2017, 12:31:25 PM1/28/17
to
If you mean there are costs for standard library implementors
and to compile times, I agree. But I don't think there's
a run-time cost for adding that function if you don't use it.


Brian

Öö Tiib

unread,
Jan 29, 2017, 2:52:30 PM1/29/17
to
The difference of 'const char* what() const' of 'std::exception'
from 'string_view' is basically that it is required to end with character
zero.

It likely feels major difference only because of Parkinson's law of
triviality. ;)

Brian Wood

unread,
Dec 18, 2020, 9:35:49 AM12/18/20
to
I wish this would have been added to 2020 C++. Perhaps it's
not too late for the next version.


Brian
Ebenezer Enterprises - In G-d we trust.
https://webEbenezer.net

Bonita Montero

unread,
Dec 18, 2020, 10:26:08 AM12/18/20
to
What's wrong with the static address ::what() returns ?

Bonita Montero

unread,
Dec 18, 2020, 10:32:25 AM12/18/20
to
> Why pay for what you don't need?
> If you have a std::string, and a lot of people do, you can avoid
> throwing away the length by using string_view rather than char*.

string_view is for integrating native memory ranges of characters
with the string-facilities so that you can peformantly combine them
with the usual string-facilities. But exceptions are very slow anyway.
So I don't see any sense other than exception::what() to return like
a normal C-string.

Öö Tiib

unread,
Dec 18, 2020, 12:18:18 PM12/18/20
to
What the what() returns is either ignored or conditionally streamed
to some kind of log in most code bases I've observed. The
string_view does not boost performance of neither operation.
Adding another virtual method to get string_view out of exception
would therefore just make binary larger as compilers can optimize
virtual calls into non-virtual or even inline those but that is not done
with caught exceptions. Also compilers do not optimize away virtual
table entries and code of such entries of used classes AFAIK.


Brian Wood

unread,
Dec 18, 2020, 1:32:46 PM12/18/20
to
It's true that syslog and some other loggers can't handle
string_view, but by the grace of G-d we are getting some C++-based
operating systems. I haven't looked at them in much depth, but
I hope they will use string_view in their APIs.

> Adding another virtual method to get string_view out of exception
> would therefore just make binary larger as compilers can optimize
> virtual calls into non-virtual or even inline those but that is not done
> with caught exceptions. Also compilers do not optimize away virtual
> table entries and code of such entries of used classes AFAIK.

How about if you use link-time optimization? Probably
static exceptions will affect some of the things you mention.


Brian
Ebenezer Enterprises

Öö Tiib

unread,
Dec 19, 2020, 4:22:42 AM12/19/20
to
The string_view is optimization where terminating zero is replaced
with length/end information. IOW it helps algorithms that
benefit from length and/or algorithms that benefit from avoiding
making copies to ensure existence of terminating zero. Exception
has to have that terminating zero for what() and loggers do simple
linear processing so particular case does not benefit much from
length information.

> > Adding another virtual method to get string_view out of exception
> > would therefore just make binary larger as compilers can optimize
> > virtual calls into non-virtual or even inline those but that is not done
> > with caught exceptions. Also compilers do not optimize away virtual
> > table entries and code of such entries of used classes AFAIK.
> How about if you use link-time optimization? Probably
> static exceptions will affect some of the things you mention.

Throw and catch being so close to each other that some kind of
interprocedural optimization affects it is unusual as people
prefer good old if in cases where issue can be handled locally.
So lets say in few lucky places virtual function can be called
non-virtually (and even potentially inlined). Those occasions do
not allow compilers to remove families of functions from virtual
tables as rest of the calls remain virtual in meaningful program.

Brian Wood

unread,
Dec 21, 2020, 12:38:11 PM12/21/20
to
OK, but I don't think I claimed some big benefit. I'm not
enthralled with 2020 C++. I mention this in the hopes
it could be included in the next standard.

> > > Adding another virtual method to get string_view out of exception
> > > would therefore just make binary larger as compilers can optimize
> > > virtual calls into non-virtual or even inline those but that is not done
> > > with caught exceptions. Also compilers do not optimize away virtual
> > > table entries and code of such entries of used classes AFAIK.
> > How about if you use link-time optimization? Probably
> > static exceptions will affect some of the things you mention.
> Throw and catch being so close to each other that some kind of
> interprocedural optimization affects it is unusual as people
> prefer good old if in cases where issue can be handled locally.
> So lets say in few lucky places virtual function can be called
> non-virtually (and even potentially inlined). Those occasions do
> not allow compilers to remove families of functions from virtual
> tables as rest of the calls remain virtual in meaningful program.

Are you saying LTO is not relevant to meaningful programs?


Brian
Ebenezer Enterprises
https://github.com/Ebenezer-group/onwards

Öö Tiib

unread,
Dec 22, 2020, 8:06:40 AM12/22/20
to
My point is that there are no reasons to. The cases where likes of
string_view are more efficient than char* are there but this is
not one. Same about cases where it is safer. The char* version
can't be removed even if string_view is better. So we would
have two virtual functions side-by-side that do same thing.

> > > > Adding another virtual method to get string_view out of exception
> > > > would therefore just make binary larger as compilers can optimize
> > > > virtual calls into non-virtual or even inline those but that is not done
> > > > with caught exceptions. Also compilers do not optimize away virtual
> > > > table entries and code of such entries of used classes AFAIK.
> > > How about if you use link-time optimization? Probably
> > > static exceptions will affect some of the things you mention.
> > Throw and catch being so close to each other that some kind of
> > interprocedural optimization affects it is unusual as people
> > prefer good old if in cases where issue can be handled locally.
> > So lets say in few lucky places virtual function can be called
> > non-virtually (and even potentially inlined). Those occasions do
> > not allow compilers to remove families of functions from virtual
> > tables as rest of the calls remain virtual in meaningful program.
> Are you saying LTO is not relevant to meaningful programs?

No. Your trying to mix static exceptions and LTO into discussion is
just red herring. LTO and static exceptions can find local optimisation
opportunity here or there. In what percentage of meaningful programs
an LTO can prove that what() of *whole* std::exception family is *never*
called virtually? About half of code of every meaningful program is
error handling so it is close to zero.
0 new messages