
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.
On 13/06/2017 21:39, Emil Dotchevski wrote: 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?)