2017-03-11 21:08 GMT+03:00 Robert Ramey via Boost
On 3/11/17 9:41 AM, Antony Polukhin via Boost wrote:
2017-03-11 20:22 GMT+03:00 Robert Ramey via Boost
: On 3/11/17 7:52 AM, Steven Watanabe via Boost wrote:
A simple extension to log such errors could be crafted from this idea and would make a great example on how to make one's own exception policy.
What is missing from this idea?
State of the Policy is missing. In many cases it could be useful to have a Policy with state to be able to get the UB info. This may be useful for different try_* functions that must not throw, usually are in hot path and rarely trigger UB:
bool try_do(int x_native) noexcept { bool was_an_error = false; safe
x(x_native, &was_an_error); // remembers that error was triggered in the `was_an_error` variable ++x; // ... other operations on `x` // ... // `x` is bad, after comparison `y` is also bad safe
y = x; // also copies pointer to `was_an_error` if (x < y) { // ... other operations on `y` } return was_an_error; }
template<class call_back> struct exception_logger { // implements ExceptionPolicy concept ... };
what's the matter with the following?
void handler(?){ ... // log the error }
bool try_do(int x_native) no_except { bool was_an_error = false safe
x{x_native}; // handler logs error ++x; // other operations on x ... } Throwing and catching an exception in such function may affect performance. Rewriting the whole function using functions from include/checked.hpp may take a lot of effort and will make the function harder to read.
But this is more like a feature request, not a blocker to the library acceptance. looks like they could be added later.
Right - we're in serious jeopardy of scope creep. Consumer of all ambitious projects.
Still, it's becoming clear that some enhancement of the ExceptionPolicy concept might create opportunities with little or no cost in conceptual integrity. We're open to modest specific suggestions.
Changes to deal with statefull policies are pretty small and could be
added any time later:
template<
class Stored,
Stored Min,
Stored Max,
class P, // promotion polic
class E // exception policy
>
class safe_base
: private P, private E /* empty base optimization will make sure
that safe_base size does not change for empty/stateless P and E */
{
BOOST_CONCEPT_ASSERT((Integer<Stored>));
BOOST_CONCEPT_ASSERT((PromotionPolicy<P>));
BOOST_CONCEPT_ASSERT((ExceptionPolicy<E>));
Stored m_t;
// ...
template<class T>
constexpr /*explicit*/ safe_base(const T & t, P p = {}, E e = {});
/* added P and E as a parameters */
// Added followin 4 functions:
const E& exception_policy() const noexcept { return *this; }
E& exception_policy() noexcept { return *this; }
const P& promotion_policy() const noexcept { return *this; }
P& promotion_policy() noexcept { return *this; }
// looks like no other changes required
};
////////
Now the example becomes the following:
struct lazy {
bool* was_an_error;
void no_error(const char *) const noexcept { *was_an_error = true; }
void uninitialized_error(const char *) const noexcept {
*was_an_error = true; }
void overflow_error(const char *) const noexcept { *was_an_error = true; }
void underflow_error(const char *) const noexcept { *was_an_error = true; }
void range_error(const char *) const noexcept { *was_an_error = true; }
void domain_error(const char *) const noexcept { *was_an_error = true; }
bool is_error() const noexcept { return *was_an_error; }
};
bool try_do(int x_native) noexcept {
bool was_an_error = false;
safe