
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.