How to write a protoprogrammed by a function?

I would like to reuse the code by writing a proto conversion that is templated by a function pointer:

template <typename Ret, typename A0, typename A1, Ret func(A0,A1)> struct apply_func : proto::callable { // Do something with func }; 

However, the function itself is polymorphic, so I do not want to indicate its exact signature.

A simplified version of what I would like my code to look like (I use external transforms for a technical reason, which, in my opinion, is not related to my current question - I could not get recursion to work without them):

 template<typename R, typename A0, typename A1> R plus_func(A0 lhs, A1 rhs) { return lhs+rhs; } template<typename R, typename A0, typename A1> R minus_func(A0 lhs, A1 rhs) { return lhs-rhs; } struct my_grammar; struct plus_rule : proto::plus<my_grammar, my_grammar> {}; struct minus_rule : proto::minus<my_grammar, my_grammar> {}; struct my_grammar : proto::or_< proto::when<proto::terminal<proto::_>, proto::_value> , proto::when<plus_rule, proto::external_transform > , proto::when<minus_rule, proto::external_transform > > {}; struct my_external_transforms : proto::external_transforms< proto::when<plus_rule, apply_func<plus_func>(my_grammar(proto::_left),my_grammar(proto::_right), proto::_state)> , proto::when<minus_rule, apply_func<minus_func>(my_grammar(proto::_left),my_grammar(proto::_right), proto::_state)> > {}; 

This does not compile because there are no arguments in the appy_func template. Is there a solution?

+6
source share
1 answer

There are several problems in the code:

  • you cannot take a pointer to a template function without specifying its template parameter, because the template will not exist until the function gets instanciated.
  • the second point, Ret (A, B), is the type of function, not the type of function pointer.
  • the function pointer is a little crude as the abstraction goes, the same can be achieved with a functor, which also solves your problem, since the polymorphic fnction object is the only type without a pattern.
  • final technical point, template conversion cannot use proto :: callable, you need to specifically specify boost :: proto :: is_callable. This is due to the langauge restriction on how inheritance is detected.

Looking through my pseudo-code, I will go for something like:

 struct plus_func { template<class Sig> struct result; template<class This,class A, class B> struct result<This(A,B)> { typedef /*whatever*/ type; }; template<class A, class B> typename result<plus_func(A const&,B const&)>::type plus_func(A const& lhs, B const& rhs) { return lhs+rhs; } }; struct minus_func { template<class Sig> struct result; template<class This,class A, class B> struct result<This(A,B)> { typedef /*whatever*/ type; }; template<class A, class B> typename result<minus_func(A const&,B const&)>::type plus_func(A const& lhs, B const& rhs) { return lhs-rhs; } }; struct my_grammar; struct plus_rule : proto::plus<my_grammar, my_grammar> {}; struct minus_rule : proto::minus<my_grammar, my_grammar> {}; struct my_grammar : proto::or_< proto::when<proto::terminal<proto::_>, proto::_value> , proto::when<plus_rule, proto::external_transform > , proto::when<minus_rule, proto::external_transform > > {}; struct my_external_transforms : proto::external_transforms< proto::when<plus_rule, apply_func<plus_func>(my_grammar(proto::_left),my_grammar(proto::_right), proto::_state)> , proto::when<minus_rule, apply_func<minus_func>(my_grammar(proto::_left),my_grammar(proto::_right), proto::_state)> > {}; 

The type returned by each PFO must be computed or specified. Beware that A, B may be const / ref qualified and may require deletion before performing type calculations.

Sidenote: external_transform is not required at all for recursive rules. I think paragraph 4 (the template being invoked) is what made it unusable.

+3
source

Source: https://habr.com/ru/post/909937/


All Articles