From: DeMarcus on
AnonMail2005(a)gmail.com wrote:
> On May 8, 1:21 pm, DeMarcus <use_my_alias_h...(a)hotmail.com> wrote:
>> Hi,
>>
>> I have a problem. I want to throw ExceptionA derived from Exception, i.e.
>>
>> struct ExceptionA : Exception
>> {
>>
>> };
>>
>> ExceptionA, ExceptionB, ExceptionC, etc. shall be able to attach text to the exception directly at construction via function
> chaining, i.e.
>> throw ExceptionA().addText( "Hello" ).addText( "World" );
>>
>> The quick way to implement that would be the following.
>>
>> struct Exception
>> {
>> Exception& addText( const std::string& str )
>> {
>> // Add str to some private string.
>> return *this;
>> }
>>
>> };
>>
>> Now, the problem comes with the throw.
>>
>> throw ExceptionA().addText( "Hello" ).addText( "World" );
>>
>> That will slice the exception and not throw an ExceptionA but instead just a plain Exception since that is what addText()
returns.
>>
>> My solution to this problem is written below, but before you scroll down and get biased; how would you solve this?
>>
>> Thanks,
>> Daniel
>>
>> My solution:
>>
>> Create a mixin to provide the addText() like this.
>>
>> struct Exception
>> {
>> void addExceptionText( const std::string& str )
>> {
>> // Add str to some private string.
>> }
>>
>> };
>>
>> template<class T>
>> struct ExceptionTextMixin
>> {
>> T& addText( const std::string& str )
>> {
>> // Use CRTP.
>> static_cast<T*>(this)->addExceptionText( str );
>> return *static_cast<T*>(this);
>> }
>>
>> };
>>
>> Now, for each ExceptionA, ExceptionB, ExceptionC, etc.
>>
>> struct ExceptionA : Exception, ExceptionTextMixin<ExceptionA>
>> {
>>
>> };
>>
>> Is it ok to use mixins and CRTP for problems like this, or will I get in trouble later?
>>
>
> Seperate the message building from your exception class and things
> will be simpler.
>
> HTH
>
>

In general, yes, but I want to provide at least a small message. If I
get a FileWriteException I want to know if it was 'access denied' or
'disk full'.

However, this quiz mainly addresses the problem with doing chaining to
temporaries. Let's say I want to add another chaining function
addErrno(), then the problem remains.


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: DeMarcus on
Hakusa(a)gmail.com wrote:
> On May 8, 1:21 pm, DeMarcus <use_my_alias_h...(a)hotmail.com> wrote:
>> Hi,
>>
>> I have a problem. I want to throw ExceptionA derived from Exception, i.e.
>>
>> struct ExceptionA : Exception
>> {
>>
>> };
>>
>> ExceptionA, ExceptionB, ExceptionC, etc. shall be able to attach text to the exception directly at construction via function
chaining, i.e.
>>
>> throw ExceptionA().addText( "Hello" ).addText( "World" );
>>
>> The quick way to implement that would be the following.
>>
>> struct Exception
>> {
>> Exception& addText( const std::string& str )
>> {
>> // Add str to some private string.
>> return *this;
>> }
>>
>> };
>>
>> Now, the problem comes with the throw.
>>
>> throw ExceptionA().addText( "Hello" ).addText( "World" );
>>
>> That will slice the exception and not throw an ExceptionA but instead just a plain Exception since that is what addText()
returns.
>
> I do not entirely understand why this is necessary. If this addText
> function is proving difficult, why not do something more obvious?
>
> std::string exceptionText = "Hello ";
> exceptionText += "world";
> throw ExceptionA( exceptionText ); // Make ctor accept string.
>
> Maybe this is overly simplistic. Maybe you want something to be done
> to the string, other than concatenation. In that case, write a
> function that concatenates the string with whatever extra you need!

I'm sorry if I was a bit unclear, but with the function chaining I want
to add more functions like addErrno(), addInnerException(),
addWhatever(). So the problem still remains.

> But, maybe ExceptionA().addText(string("x")+string("y")) will have a
> different effect than ExceptionA().addText("x").addText("y"). Then how
> about this:
>
> // Assuming that overloading this function per type is
> impractical.
> template< typename E >
> E addText( E e, string str )
> {
> e.addText( str );
> return e;
> }
>
> // Somewhere, later on...
> throw addText( addText(ExceptionA(), "Hello"), "World" );
>
> Using C++0x, there are variadic templates and a variadic ctor would
> solve this whole problem, no? G++ currently supports this, but i don't
> believe MSVC does... yet.
>

Could be one way to go, but I'd prefer function chaining since it's more
clear about what's going on.

> I think this problem should be defined more clearly. If addText does
> nothing but adds text, concatenation, then my first solution is
> adequate, just a little inconvenient for getting it all done in one
> line. If addText does anything more, then my last solution should be
> adequate.
>
> Though, ignoring all that, what's wrong with this:
>
> ExceptionA e;
> e.addText("x").addText("y");
> throw e;
>
> Is part of the specification for the problem "Must be done in one
> line."? All this seems like a lot of work for just pretty syntax,
> unless i'm missing something.
>
>

Yes, you are completely right, that is why I brought this question here.
Is it possible to make the syntax even better without drawbacks? I.e.

throw ExceptionA().addText("x").addText("y");


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: DeMarcus on
�� Tiib wrote:
> On 8 mai, 20:21, DeMarcus <use_my_alias_h...(a)hotmail.com> wrote:
>> Hi,
>>
>> I have a problem. I want to throw ExceptionA derived from Exception, i.e.
>>
>> struct ExceptionA : Exception
>> {
>>
>> };
>>
>> ExceptionA, ExceptionB, ExceptionC, etc. shall be able to attach text to the exception directly at construction via function
chaining, i.e.
>>
>> throw ExceptionA().addText( "Hello" ).addText( "World" );
>>
>> The quick way to implement that would be the following.
>>
>> struct Exception
>> {
>> Exception& addText( const std::string& str )
>> {
>> // Add str to some private string.
>> return *this;
>> }
>>
>> };
>>
>> Now, the problem comes with the throw.
>>
>> throw ExceptionA().addText( "Hello" ).addText( "World" );
>>
>> That will slice the exception and not throw an ExceptionA but instead just a plain Exception since that is what addText()
returns.
>>
>> My solution to this problem is written below, but before you scroll down and get biased; how would you solve this?
>
>
> I would perhaps use templated operator <<. It looks better when it is
> used in such places.
>
> struct Exception
> {
> void addText( const std::string& str )
> {
> // Add str to some private string.
> }
>
> };
>
> struct ExceptionA : Exception
> {};
>
> template < class E >
> E& operator<<( E& x, std::string txt )
> {
> x.addText( txt );
> return x;
> }
>
> int main()
> {
> throw ExceptionA() << "Hello" << "World";
> }
>
>

When it comes to text, yes. The thing is that I want to chain some more
data like addErrno() and maybe in the future; addInfoURL(). Then
operator<<() won't do if two types of data both can be strings. It would
be nice to have something like

template<class E>
E& operator addText( E& x, std::string txt )
{
x.addTextToException( txt );
return x;
}

int main()
{
throw ExceptionA().addText( "Hello" );
}

Maybe it shouldn't be called operator but rather binary_function or
something.


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: DeMarcus on
Goran wrote:
> On May 8, 7:21 pm, DeMarcus <use_my_alias_h...(a)hotmail.com> wrote:
>> Hi,
>>
>> I have a problem. I want to throw ExceptionA derived from Exception,
>> i.e.
>>
>> struct ExceptionA : Exception
>> {
>>
>> };
>>
>> ExceptionA, ExceptionB, ExceptionC, etc. shall be able to attach text
>> to the exception directly at construction via function chaining, i.e.
>>
>> throw ExceptionA().addText( "Hello" ).addText( "World" );
>>
>> The quick way to implement that would be the following.
>>
>> struct Exception
>> {
>> Exception& addText( const std::string& str )
>> {
>> // Add str to some private string.
>> return *this;
>> }
>>
>> };
>>
>> Now, the problem comes with the throw.
>>
>> throw ExceptionA().addText( "Hello" ).addText( "World" );
>>
>> That will slice the exception and not throw an ExceptionA but instead
>> just a plain Exception since that is what addText() returns.
>>
>> My solution to this problem is written below, but before you scroll
>> down and get biased; how would you solve this?
>
> boost::exception does that already, and better, because it allows you
> to attach arbitrary info to exception object (you're only trying
> text). My guess is that http://www.boost.org/doc/libs/1_43_0/libs/exception/doc/tutorial_transporting_data.html
> is exactly what you're looking for.
>
> Goran.
>
>

Well, I just had a wild discussion May 05 about boost::exception in
comp.lang.c++ with subject "Do you have experience with exceptions?"

Though the chaining function in boost::exception is pure handcraft I
still claim that it's not the way to go because in their case the
receiver has to know what data arrives, and that is not far from type
switching.

Instead data should be provided through the interface, i.e. for example
getErrno(), or through the visitor pattern.

Thanks anyway!


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Goran on
On May 11, 4:24 pm, DeMarcus <use_my_alias_h...(a)hotmail.com> wrote:
> Goran wrote:
> > On May 8, 7:21 pm, DeMarcus <use_my_alias_h...(a)hotmail.com> wrote:
> >> Hi,
>
> >> I have a problem. I want to throw ExceptionA derived from Exception,
> >> i.e.
>
> >> struct ExceptionA : Exception
> >> {
>
> >> };
>
> >> ExceptionA, ExceptionB, ExceptionC, etc. shall be able to attach text
> >> to the exception directly at construction via function chaining, i.e.
>
> >> throw ExceptionA().addText( "Hello" ).addText( "World" );
>
> >> The quick way to implement that would be the following.
>
> >> struct Exception
> >> {
> >> Exception& addText( const std::string& str )
> >> {
> >> // Add str to some private string.
> >> return *this;
> >> }
>
> >> };
>
> >> Now, the problem comes with the throw.
>
> >> throw ExceptionA().addText( "Hello" ).addText( "World" );
>
> >> That will slice the exception and not throw an ExceptionA but instead
> >> just a plain Exception since that is what addText() returns.
>
> >> My solution to this problem is written below, but before you scroll
> >> down and get biased; how would you solve this?
>
> > boost::exception does that already, and better, because it allows you
> > to attach arbitrary info to exception object (you're only trying
> > text). My guess is thathttp://www.boost.org/doc/libs/1_43_0/libs/exception/doc/tutorial_tran...
> > is exactly what you're looking for.
>
> > Goran.
>
> Well, I just had a wild discussion May 05 about boost::exception in
> comp.lang.c++ with subject "Do you have experience with exceptions?"
>
> Though the chaining function in boost::exception is pure handcraft I
> still claim that it's not the way to go because in their case the
> receiver has to know what data arrives, and that is not far from type
> switching.
>
> Instead data should be provided through the interface, i.e. for example
> getErrno(), or through the visitor pattern.

Hmmm... boost::exception gives you that just as well, because nothing
stops you from providing the abstract interface in both base exception
object and error_info object. In these abstract interfaces, you
specify what you want. You use base classes at the catch site and
you're done. But I concede, if what you want is simply the abstract
interface (e.g. error text and a number), boost::exception is an
overkill.

I don't like that "abstract base" approach particularly, because there
is always that annoying case where, at the catch site, I need to do
something, depending on a particular condition that I can't possibly
put into said abstract interface.

In other words, I believe that reality is: sometimes, I have to couple
throw site and catch site. Or else, I have to do some major ugliness
in the interface, or reach for a major contortion in a much bigger
part of the code, only to satisfy some special case.

(Clearly, that's why I believe boost::exception does it right, too.).

Goran.


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]