Andrew Venikov wrote:
Unfortunately, it seems that using '<<' syntax it will be impossible to
catch exceptions. I hate macros as much as the next guy, but it looks
like this sort of problem is solvable only using macros.
Well, when I said that in my previous post, I spoke too soon.
It looks like there actually may be a way. At least for the simple
cases. The problem currently is that error_info constructor
expects an already constructed object of value_type. The construction
of value_type happens outside of error_info's constructor, so we
can't catch it.
But if we generate error_info in such a way that we would mimic all
value_type's constructors, e.g. generate error_info constructors with
value_type's signatures, then we could do value_type construction
right in error_info constructor body, thus having an ability to catch
all exceptions. If exception happens, then we would make the current
error_info essentially a dud. If not, then we could swap out the local
object with a value_type member of error_info.
To generate these constructors we would use SFINAE with a dummy
construction of value_type using error_info's argument types.
Like this:
template
class error_info
{
value_type v_;
...
public:
//Constructor with one argument
template <typename T>
error_info(T in,
int2type * dummy =0)
{
try
{
value_type temp(in);
v_.swap(temp);
}
catch(...)
{
//Mark this object as a "dud"
}
}
//Constructor with two arguments
template
error_info(T1 in1, T2 in2,
int2type * dummy =0)
{
try
{
value_type temp(in1, in2);
v_.swap(temp);
}
catch(...)
{
//Mark this object as a "dud"
}
}
//And so forth
....
};
error_info ErrorDescriptor;
throw AnError() << ErrorDescriptor("abcd"); //Will guarantee
//that even if string() throws an exception,
//AnError() is propagated.
The above code assumes that value_type has a swap member function. The
code can be changed to use boost::move (or new std::move), but I'm not
yet terribly familiar with those, that's why I didn't use them. I was
just trying to show the concept. All we need to know is that value_type
is movable.
Of course, this will not help us if error_info() is initialized with
initializers that in turn may throw exception (like calling a function).
But I expect those cases to be rare. And in any case, that's in user's
control. But at least we've eliminated a problem that was out of user's
control.
Andy.