Boost logo

Boost :

Subject: Re: [boost] Noexcept
From: Gavin Lambert (gavinl_at_[hidden])
Date: 2017-06-13 23:33:19


On 13/06/2017 21:39, Emil Dotchevski wrote:
> I can't imagine a function which returns shared_ptr<T> *and* which
> could fail, to return an empty one in case of success. That said, in
> that case all it means is that you can't use throw_ directly in a
> return expression; or you could partially specialize throw_return<>
> for a specific type of shared_ptr, if that's appropriate.
private:
void create_X_if_needed() noexcept
{
     if (!m_X)
     {
         try
         {
             m_X = make_shared<X>();
         }
         catch (internal_error const& e)
         {
             throw_(e.code());
         }
     }
}

public:
shared_ptr<X> get_X_if_enabled() noexcept
{
     if (feature_X_enabled())
     {
         create_X_if_needed();
     }
     return m_X;
}

get_X_if_enabled() could return an empty pointer in two cases:

   1. If feature_X_enabled() returns false during all calls, this is a
successful return with no pointer.
   2. If X's constructor throws an internal_error, this is an error code
return with no pointer.

> Regardless, the correct way to check for errors is to see if the result is
> valid. This is the price one must pay when not using exception handling.

Isn't the correct way to check for errors (without explicitly catching
errors) in this case to call has_current_error()?

Granted in this case get_X_if_enabled doesn't actually need to
explicitly check for errors since the following statements will work
regardless of whether there was an error state or not. But say if it
wanted to do some logging only in the case where create_X_if_needed
didn't fail, that would have to be written something like this:

shared_ptr<X> get_X_if_enabled() noexcept
{
     if (feature_X_enabled())
     {
         create_X_if_needed();
         if (!has_current_error())
         {
            log("has X");
         }
     }
     return m_X;
}

The other possibility is to catch and rethrow the error, but that seems
more cumbersome and error-prone.

(Related: if the original throw_ was a custom type not derived from
std::exception, and catch<> is used to catch it as a std::exception and
throw_ it again, can it still be caught later with a
catch_<custom_error>? Does the answer depend on whether throw_() or
throw_(e) was used?)


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk