From: DeMarcus on
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?


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

From: AnonMail2005 on
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


--
[ 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 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.


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

From: Hakusa on
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!
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.

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.


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

From: Öö Tiib on
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";
}


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