|
Boost Users : |
Subject: Re: [Boost-users] exception: use of error_info can mask real exceptions
From: Andrew Venikov (andrew.venikov_at_[hidden])
Date: 2009-05-25 03:12:16
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 Tag, typename value_type>
class error_info
{
value_type v_;
...
public:
//Constructor with one argument
template <typename T>
error_info(T in,
int2type<sizeof(new value_type(T()))> * dummy =0)
{
try
{
value_type temp(in);
v_.swap(temp);
}
catch(...)
{
//Mark this object as a "dud"
}
}
//Constructor with two arguments
template <typename T1, typename T2>
error_info(T1 in1, T2 in2,
int2type<sizeof(new value_type(T1(), T2()))> * dummy =0)
{
try
{
value_type temp(in1, in2);
v_.swap(temp);
}
catch(...)
{
//Mark this object as a "dud"
}
}
//And so forth
....
};
error_info<struct a_tag, std::string> 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.
Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net