Как мне написать протопреобразование на основе функции? - PullRequest
6 голосов
/ 04 марта 2012

Я хотел бы повторно использовать код, написав протопреобразование, которое задается указателем функции:

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

Однако сама функция полиморфна, поэтому я не хочу указывать ее точную подпись.1004 *

Ниже приведена упрощенная версия того, как должен выглядеть мой код (я использую внешние преобразования по технической причине, которая, по моему мнению, не связана с моим текущим вопросом - я не смог заставить рекурсию работать без них):

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)>
    >
{};

Это не компилируется, потому что в шаблоне appy_func отсутствуют аргументы.Есть ли решение?

1 Ответ

3 голосов
/ 09 марта 2012

У вас есть несколько проблем в вашем коде:

  • вы не можете взять указатель на функцию шаблона, не указав его параметр шаблона, так как шаблон не будет существовать, пока функция не будет создана.
  • вторая точка, Ret (A, B) - это тип функции, а не тип указателя функции.
  • указатель на функцию является немного необработанным в процессе абстракции, то же самое можно сделать с помощью функтора, который также решит вашу проблему, так как полиморфный объект fnction является единственным типом, не являющимся шаблоном.
  • последний технический момент, шаблон преобразования не может использовать proto :: callable, вы должны явно специализировать boost :: proto :: is_callable. Это связано с языковым ограничением на способ обнаружения наследования.

Просматривая ваш псевдокод, я пойду на что-то вроде:

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)>
    >
{};

Тип, возвращаемый каждым PFO, должен быть вычислен или указан. Помните, что A, B могут иметь квалификацию const / ref и могут нуждаться в удалении перед выполнением вычисления типа.

Sidenote: external_transform вообще не требуется для рекурсивных правил. Я предполагаю, что пункт 4 (вызываемый шаблон) заставил его не работать.

...