From: Dragan Milenkovic on
DeMarcus 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" );

IMHO, the best argument was the first one you got. Separate
responsibilities. This is one of the most important concepts
if you desire a clean and understandable design.
But, since you don't want to listen to reason, :-D
let me make a few attempts...

make_exception<ExceptionA>().addText("Hello").addText("World")
.addImage(image).throw_me();

or do it to an existing exception:

chain_wrapper(excA).addText("Hello").addText("World").throw_me();

or with variadic templates:

chain_and_throw<ExceptionA>(textAdder("Hello"), textAdder("World"));

or with a std::initializer_list:

chain_and_throw<ExceptionA>({textAdder("Hello"), textAdder("World")});

or another flavor:

chain_and_throw(excA, {textAdder("Hello"), textAdder("World")});

or a variation of the first one:

throw make_exception<ExceptionA>().addText("Hello").addText("World")
.addImage(image).exception;

how about:

throw chain_wrapper(excA)(textAdder << "Hello" << "World")
(imageAdder << image).exception;

etc... but please note that I didn't go pretty with the names.

It just occurred to me... I _did_ separate responsibilities
in each sample, didn't I? :-)

--
Dragan

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

From: Michael Herstine <sp1ff on
>>> 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.

[snip]

>>
>> 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");

Maybe I'm not fully appreciating the problem, here, but it seems to me
you want to succinctly "attach" data to the exception in a way
expressable through interface (as oppossed to boost::exception). Why
not just use the constructor?

--
Michael <sp1ff(a)pobox.com>

web o http://www.unwoundstack.com
ICQ o 198685593

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

From: Öö Tiib on
On May 11, 5:25 pm, DeMarcus <use_my_alias_h...(a)hotmail.com> wrote:
> 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.

No, it would make parsing and name resolving C++ way harder (and it is
not simple already).

I myself use things similar to BOOST_THROW_EXCEPTION(), but instead of
throwing the debug information (that catcher has likely nothing to do
with) i prefer to log it right away.

Putting lot of data with exception is often not that useful for
catcher since stack has been unrolled and there is no much to repair
anyway.

One thing i like to have with exception (besides describing text) is
error code. All the relevant static data (like urls for web-pages,
images, colors, severities, translations and what not) are not worth
to be thrown anyway. Catcher has error code and so can ask all the
rest from "debugging department" based on that code.


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

From: DeMarcus on
On 2010-05-21 05:34, Michael Herstine <sp1ff(a)pobox.com> wrote:
>>>> 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.
>
> [snip]
>
>>>
>>> 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");
>
> Maybe I'm not fully appreciating the problem, here, but it seems to me
> you want to succinctly "attach" data to the exception in a way
> expressable through interface (as oppossed to boost::exception). Why
> not just use the constructor?
>

Using the constructor was my first attempt. However, lately I've started
to appreciate function chaining, especially for optional parameters
where the number of parameters may grow.

Having n optional parameters in the constructor will give you 2^n
constructors unless you use pointers that can be null. Not using
pointers will also get you into trouble if two parameters are of the
same type. Therefore, in this case, I found function chaining more
appealing than putting the parameters in the constructor.



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

From: DeMarcus on
On 2010-05-19 18:14, Dragan Milenkovic wrote:
> DeMarcus 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" );
>
> IMHO, the best argument was the first one you got. Separate
> responsibilities. This is one of the most important concepts
> if you desire a clean and understandable design.
> But, since you don't want to listen to reason, :-D
> let me make a few attempts...
>
> make_exception<ExceptionA>().addText("Hello").addText("World")
> .addImage(image).throw_me();
>
> or do it to an existing exception:
>
> chain_wrapper(excA).addText("Hello").addText("World").throw_me();
>
> or with variadic templates:
>
> chain_and_throw<ExceptionA>(textAdder("Hello"), textAdder("World"));
>
> or with a std::initializer_list:
>
> chain_and_throw<ExceptionA>({textAdder("Hello"), textAdder("World")});
>
> or another flavor:
>
> chain_and_throw(excA, {textAdder("Hello"), textAdder("World")});
>
> or a variation of the first one:
>
> throw make_exception<ExceptionA>().addText("Hello").addText("World")
> .addImage(image).exception;
>
> how about:
>
> throw chain_wrapper(excA)(textAdder << "Hello" << "World")
> (imageAdder << image).exception;
>

Aha, so you make the last function exception() virtual and implement
that in each exception like this?

ExceptionA& exception()
{
return *this;
}

Smart!

That was a whole bunch of new ideas. Thanks!


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