Boost logo

Boost :

From: Alexander Nasonov (alnsn_at_[hidden])
Date: 2002-11-12 04:35:22


Douglas Gregor wrote:

> On Monday 11 November 2002 11:45 am, Alexander Nasonov wrote:
>> Implementation can first try to call 'call_ex' and if it throws internal
>> exception (default behavoir) then revert to 'call' member-function.
>
> I'm assuming you aren't referring to an actual C++ exception. I would
> assume that the default behavior of call_ex would be to call the call
> function in the derived class (assuming you are still planning to use the
> curiously recurring template pattern).

Exception was a first thing that came into my mind. Thank you Douglas for
your idea! This is what we have now:

  template<class EndFunction, typename Signature>
  struct function
  {
    // actually, result_type may depend on OperationList
    // const correctness issues are skiped for simplicity

    template<class OperationLlist>
    result_type operator()(any<OperationList> & a, any<OperationList> & b)
    {
      EndFunction & func = static_cast<EndFunction &>(*this);
      // pseudo-algorithm
      if(!can_make_call)
        return func.nocall(a, b);
      else
      {
        // assume that 'a' holds v1 and 'b' holds v2
        return func.call_ex(v1, typeid(v1), v2, typeid(v2));
      }
    }

    template<typename T>
    result_type call_ex(const T & a, const std::type_info &,
                        const T & b, const std::type_info &)
    {
      EndFunction & func = static_cast<EndFunction &>(*this);
      return func.call(a, b);
    }

    template<typename T>
    result_type call(const T & a, const T & b)
    {
      // One of 'call_ex' or 'call' must be overriden by EndFunction
      BOOST_STATIC_ASSERT(false);
    }

    template<class OperationLlist>
    result_type nocall(any<OperationList> & a, any<OperationList> & b)
    {
      throw nocall();
    }

    // ...
  };

  // Example (two different versions of less):

  struct simple :
    struct function<simple, bool (const arg &, const arg &)>
  {
    template<typename T>
    bool call(const T & a, const T & b)
    {
      return a < b;
    }
  };

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

    template<class OperationLlist>
    bool nocall(any<OperationList> & a, any<OperationList> & b)
    {
      return a.type().before(b.type());
    }
  };

  boost::dynamic_any::any<mpl::list<simple, advanced> > a(0), b(1), c;

  bool d = simple()(a, b);
  assert(d);

  bool e = advanced()()(a, b);
  assert(e);

  bool f = advanced()()(b, c);
  assert(f == typeid(int).before(typeid(void)));

  bool g = simple()(b, c); // throws nocall

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


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk