|
Boost : |
Subject: Re: [boost] [yap] Review part 1: documentation
From: Steven Watanabe (watanabesj_at_[hidden])
Date: 2018-02-13 03:13:08
AMDG
On 02/12/2018 06:09 PM, Zach Laine wrote:
> On Mon, Feb 12, 2018 at 12:08 PM, Steven Watanabe via Boost <
> boost_at_[hidden]> wrote:
>
>> <snip>
>> Unwrapping the terminals causes surprising behavior,
>> which is only sort of fixed by automatically applying
>> the terminal transform and making transform a no-op
>> for non-Expressions. In particular, if the terminal
>> transform returns an Expression, that Expression will
>> get processed again.
>
>
> Yes, I'm not entirely satisfied with this either, for the same reasons.
> FWIW, the design has settled here after previously not doing any automatic
> terminal unwrapping, but I found it substantially harder to use when that
> was the case. I find that code like what you wrote here infrequently trips
> over whether Expr is an Expression or a non-Expression type, but when it
> does you can write it like this:
>
> auto operator()(plus_tag, Expr&& lhs, Expr&& rhs)
> {
> transform(as_expr(lhs), *this);
> transform(as_expr(rhs), *this)
> }
>
> Not the greatest, but like I said, I don't think the full generality here
> is required all that often.
>
I don't think as_expr helps with the problems I'm thinking of.
Unless I'm misunderstanding something, the following
(seemingly reasonable) code will blow up the stack with
infinite recursion:
int check_int(int i)
{
assert(i >= -42 && i < 42);
return i;
}
int checked_add(int i, int j)
{
return check_int(i + j);
}
struct checked_call
{
template<class F>
int operator()(F f, int i)
{
return check_int(f(i));
}
};
struct int_checker
{
auto operator()(terminal_tag, placeholder<I>)
{
return make_expression<expr_kind::call>(check_int,
placeholder<I>{});
}
template<class L, class R>
auto operator()(plus_tag, L && lhs, R && rhs)
{
return make_expression<expr_kind::call>(checked_add,
transform(lhs, *this), transform(rhs, *this));
}
template<class F, class E>
auto operator()(call_tag, F&& f, E&&... e)
{
return make_expression<expr_kind::call>(checked_call{},
f, transform(e, *this)...);
}
};
abs_ = make_terminal((int(*)(int))&std::abs);
evaluate(transform(abs_(1_p + 2_p), int_checker{}), -5, 20);
In Christ,
Steven Watanabe
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk