.. Copyright David Abrahams 2006. Distributed under the Boost
.. Software License, Version 1.0. (See accompanying
.. file LICENSE_1_0.txt or copy at
.. http://www.boost.org/LICENSE_1_0.txt)

How Runtime Polymorphism is expressed in Boost.Python:
-----------------------------------------------------

   struct A { virtual std::string f(); virtual ~A(); };

   std::string call_f(A& x) { return x.f(); }

   struct B { virtual std::string f() { return "B"; } };

   struct Bcb : B
   { 
      Bcb(PyObject* self) : m_self(self) {}

      virtual std::string f() { return call_method<std::string>(m_sef, "f"); }
      static std::string f_default(B& b) { return b.B::f(); }

      PyObject* m_self;
   };

   struct C : B
   {
      virtual std::string f() { return "C"; }
   };

   >>> class D(B):
   ...     def f():
   ...         return 'D'
   ...
   >>> class E(B): pass
   ...


When we write, "invokes B::f non-virtually", we mean:

  void g(B& x) { x.B::f(); }

This will call B::f() regardless of the dynamic type of x. Any other
way of invoking B::f, including through a function pointer, is a
"virtual invocation", and will call the most-derived override of f().

Case studies

   C++\Python class
       \___A_____B_____C_____D____E___
       |
   A   |   1
       |
   B   |   2     3
       |
   Bcb |         4           5    6
       |
   C   |         7     8
       |


1. Simple case

2. Python A holds a B*. Probably won't happen once we have forced
   downcasting. 

   Requires:
         x.f() -> 'B'
         call_f(x) -> 'B'

   Implies: A.f invokes A::f() (virtually or otherwise)

3. Python B holds a B*. 

   Requires:
        x.f() -> 'B'
        call_f(x) -> 'B'
   
   Implies: B.f invokes B::f (virtually or otherwise)


4. B constructed from Python

   Requires:

        x.f() -> 'B'
        call_f(x) -> 'B'

   Implies: B.f invokes B::f non-virtually. Bcb::f invokes B::f
            non-virtually.

   Question: Does it help if we arrange for Python B construction to
   build a true B object? Then this case doesn't arise.


5. D is a Python class derived from B

   Requires:

        x.f() -> 'D'
        call_f(x) -> 'D'

   Implies: Bcb::f must invoke call_method to look up the Python
            method override, otherwise call_f wouldn't work.

6. E is like D, but doesn't override f

   Requires:

        x.f() -> 'B'
        call_f(x) -> 'B'

   Implies: B.f invokes B::f non-virtually. If it were virtual, x.f()
            would cause infinite recursion, because we've already
            determined that Bcb::f must invoke call_method to look up
            the Python method override.

7. Python B object holds a C*

   Requires:
        
        x.f() -> 'C'
        call_f(x) -> 'C'

   Implies: B.f invokes B::f virtually. 

8. C object constructed from Python

   Requires:

        x.f() -> 'C'
        call_f(x) -> 'C'

   Implies: nothing new.

------

Total implications:

2: A.f invokes A::f() (virtually or otherwise)
3: B.f invokes B::f (virtually or otherwise)
4: B.f invokes B::f non-virtually. Bcb::f invokes B::f non-virtually
6: B.f invokes B::f non-virtually. 
7: B.f invokes B::f virtually. 

5: Bcb::f invokes call_method to look up the Python method

Though (4) is avoidable, clearly 6 and 7 are not, and they
conflict. The implication is that B.f must choose its behavior
according to the type of the contained C++ object. If it is Bcb, a
non-virtual call to B::f must occur. Otherwise, a virtual call to B::f
must occur. This is essentially the same scheme we had with
Boost.Python v1.

Note: in early versions of Boost.Python v1, we solved this problem by
introducing a new Python class in the hierarchy, so that D and E
actually derive from a B', and B'.f invokes B::f non-virtually, while
B.f invokes B::f virtually. However, people complained about the
artificial class in the hierarchy, which was revealed when they tried
to do normal kinds of Python introspection.

-------

Assumption: we will have a function which builds a virtual function
dispatch callable Python object.

     make_virtual_function(pvmf, default_impl, call_policies, dispatch_type)

Pseudocode:

     Get first argument from Python arg tuple
     if it contains dispatch_type
        call default_impl
     else
        call through pvmf


Open questions:

   1. What about Python multiple inheritance? Do we have the right
      check in the if clause above?
      
      A: Not quite. The correct test looks like:

      Deduce target type of pvmf, i.e. T in R(T::*)(A1...AN).
      Find holder in first argument which holds T
      if it holds dispatch_type...

   2. Can we make this more efficient?
     
     The current "returning" mechanism will look up a holder for T
     again. I don't know if we know how to avoid that.


  OK, the solution involves reworking the call mechanism. This is
  neccesary anyway in order to enable wrapping of function objects.

  It can result in a reduction in the overall amount of source code,
  because returning<> won't need to be specialized for every
  combination of function and member function... though it will still
  need a void specialization. We will still need a way to dispatch to
  member functions through a regular function interface. mem_fn is
  almost the right tool, but it only goes up to 8
  arguments. Forwarding is tricky if you don't want to incur copies.
  I think the trick is to use arg_from_python<T>::result_type for each
  argument to the forwarder.

  Another option would be to use separate function, function object,
  and member function dispatchers. Once you know you have a member
  function, you don't need cv-qualified overloads to call it.

  Hmm, while we're at this, maybe we should solve the write-back
  converter problem. Can we do it? Maybe not. Ralf doesn't want to
  write special write-back functions here, does he? He wants the
  converter to do the work automatically. We could add
  cleanup/destructor registration. That would relieve the client from
  having accessible destructors for types which are being converted by
  rvalue. I'm not sure that this will really save any code,
  however. It rather depends on the linker, doesn't it? I wonder if
  this can be done in a backwards-compatible fashion by generating the
  delete function when it's not supplied?

  
