I'm trying to redesign functions for dynamic_any. Currenly, I have this:

  struct less : function_vv<bool>
  {
    template<typename T>
    bool operator()(const T & a, const T & b) const
    {
      return a < b;
    }
  };

Two trailing 'v' in function_vv are indicators that less accepts two 
arguments by value or const reference. First change I'm going to make is to 
remove these trailing letters and to introduce more natural syntax (idea is 
taken from Boost.Function):

  struct less : function<bool (const arg &, const arg &)>
  {
    template<typename Arg>
    bool operator()(const Arg & a, const Arg & b) const
    {
      return a < b;
    }
  };

The 'arg' is a placeholder for pseudo-template parameter. Compare it with 
Arg defined in less::operator() and with less::operator() signature.

This change doesn't solve other problem: using of a 'call' function:

  using namespace boost;
  using namespace boost::dynamic_any;

  any<mpl::list<less> > a, b;
  bool result = call(less(), a, b); // here is a problem

I would like it to be:

  any<mpl::list<less> > a, b;
  bool result = less()(a, b); // much better

Curiously recurring pattern suits fine here. Let the class template 
'function' to accept end function (less in our case). Call operator that 
takes two 'any' values can be implemented inside the 'function' (constness 
of arguments leaved apart for simplicity):

  template<class EndFunction, typename Signarure>
  struct function
  {
    template<class OperationLlist>
    typename function_result<OperationList, EndFunction>::type
    operator()(any<OperationList> & a, any<OperationList> & b)
    {
      // implementation
    }

    // implementation
  };

But it will be hidden by the call operator defined in EndFunction. 
EndFunction::operator() should be renamed:

  struct less : function<less, bool (const arg &, const arg &)>
  {
    // note the name
    template<typename Arg>
    bool call(const Arg & a, const Arg & b) const
    {
      return a < b;
    }
  };

Additionally, two types of control are desired:
1) Control over real types of arguments. It is a limitation of dynamic_any 
library that arguments must be converted to _one_ type before a call. But 
they can be of different types. Problem can be easily solved by adding 
additional arguments to the 'call' member-function:

  template<typename Arg>
  bool less::call(const Arg & a, const std::type_info & ta,
                  const Arg & b, const std::type_info & tb) const
  {
    return a < b;
  }

2) Controlled behavior when the call cannot be made. I propose to make it 
over 'nocall' member-function. Default handler can be implemented inside 
the 'function' as a single throw statement. Those users who wish other 
behavior can override 'nocall'.

As a summary I can demonstrate less function that compares first by type and 
then by value:

  struct less : function<less, bool (const arg &, const arg &)>
  {
    template<typename Arg>
    bool call(const Arg & a, const std::type_info & ta,
              const Arg & b, const std::type_info & tb) const
    {
      return (ta == tb) ? (a < b) : ta.before(tb);
    }

    template<typename OperationList>
    bool nocall(const any<OperationList> & ta,
                const any<OperationList> & tb) const
    {
      return a.type().before(b.type());
    }
  };

  // Example:
  typedef any<mpl::list<less> > any_less;
  std::vector<any_less> v = get_it();
  std::sort(v.begin(), v.end(), less());

How do you like it?

Best regards,
Alexander Nasonov
mailbox: alnsn
server: mail.ru



_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Reply via email to