Boost logo

Boost :

Subject: Re: [boost] [yap] Review part 1: documentation
From: Steven Watanabe (watanabesj_at_[hidden])
Date: 2018-02-13 03:13:08


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,
  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, gregod at, cpdaniel at, john at