Boost logo

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