Interfaces.cpp

// Interfaces.cpp
//
// Author David Barrett-Lennard, Jesse Pepper
// (C)opyright Cedanet Pty Ltd 2007

@import "Ceda/cxObject/Object.h"
@import "Ceda/cxObject/IObjectVisitor.h"
@import "ExampleUtils.h"
#include "Ceda/cxUtils/xstring.h"
#include <assert.h>

/*
Xcpp provides an alternative mechanism for achieving dynamic polymorphism.  The technique has been 
described in the literature.  See for example C. Diggins,  or the Boost Interfaces Library (BIL)

Firstly we briefly review how dynamic polymorphism is achieved in C++.

Dynamic polymorphism in C++
---------------------------

In C++ dynamic polymorphism is achieved by declaring virtual methods in classes.  Typically the 
compiler adds hidden variables called vtable pointers as part of the object's state in order to 
support dynamic dispatch of called methods.

For example

    struct Shape
    {
		virtual float64 GetArea() const = 0;
		virtual float64 GetPerimeter() const = 0;
    };

Shape is a pure abstract class.  Any concrete class that inherits from Shape will need to implement
the given methods.  Objects that implement Shape will contain a vtable pointer.  A client with a 
pointer to a Shape object is able to call the methods without knowing its concrete type.

Xcpp interface definitions
--------------------------

An xcpp interface is defined like this

	$interface IShape
	{
		float64 GetArea() const;
		float64 GetPerimeter() const;
	};

Note that there is no 'virtual' qualifier and no '= 0' syntax.

Interface pointers and polymorphic method invocation
----------------------------------------------------

A client that has an interface pointer can invoke methods polymorphically.  For example

    void foo(ptr<IShape> s)
    {
        float64 area = s->GetArea();
    }

This represents a dynamic dispatch that allows for polymorphism.  foo() is able to call GetArea()
on many different classes.

Interface pointer coercion
--------------------------

The most significent difference with xcpp interfaces over more conventional approaches is that the
polymorphic capability is not type intrusive because the vtable pointer is not stored within the 
object itself.  Instead it forms part of the interface pointer used by clients to invoke methods 
polymorphically.

For example, consider the following

	struct Circle
	{
		Circle() r(2.0) {}
		
		float64 GetArea() const { return PI*r*r; }
		float64 GetPerimeter() const { return 2*PI*r; }

		float64 r;
	};

	Circle c;
	ptr<IShape> s = &c;     // Coerce circle c into an IShape

Note well that the Circle class conforms to the signature (and semantics) expected by the IShape
interface and therefore can be coerced into a ptr<IShape> as shown.  This is achieved without any
need to modify the Circle class which in itself knows nothing about the IShape interface.

The size of the Circle class is 8 bytes (the size of its float64 member).  xcpp interfaces allow
small objects to implement any number of interfaces without any vtable pointers within the object.

Notes on programming with $interfaces
-------------------------------------

Normally when writing class hierarchies the programmer must juggle two different kinds of 
inheritance.

*   Type inheritance
    The derived class is a sub-type of its base class.

*   Implementation inheritance
    The derived class inherits member variables and implementations of member functions from its 
    base class.

These two forms of inheritance are quite different in nature.  As a result, a good strategy when
using abstract base classes is to define lots of *pure* (i.e. stateless) abstract base classes.  This
allows the programmer to distinguish inheritance of type from inheritance of state and avoid 
confusion in the design.

Programming with $interfaces offers a better strategy.

A programmer should write a concrete class without any concern for polymorphism.  This is great
because it clears the mind!  Template mixins and the Barton and Nackman Trick for curiously 
recurring templates allow a base class to make calls on the final class.  This is better than the 
"Template Method" design pattern because it avoids the overhead of a virtual function call, and 
perhaps more importantly allows for inlining.   

The relationships between derived and base classes are expressed far more elegantly through 
template mixins.   For example

    template <typename Final, typename Base>
    class SizeMixin : public Base
    {
    public:
        SizeMixin() : width_(0), height_(0) {}
    
        void Serialise(Archive& ar)
        {
            Base::Serialise(ar);
            ar << width_ << height_;
        }

        int GetWidth() const { return width_; }
        int GetHeight() const { return height_; }
        int GetArea() const { return width_ * height_; }

        void SetWidth(int width) { width_ = width; static_cast<Final*>(this)->OnSetWidth(); }
        void SetHeight(int height) { height_ = height; static_cast<Final*>(this)->OnSetHeight(); }

        void OnSetWidth() {}
        void OnSetHeight() {}
    private:
        int width_;
        int height_;    
    };

This mixin can be used for any class that needs width and height members.  Mixins like this have
the potential to save a lot of repetitive code.  Trying to inherit code like this without it being 
templatised is inferior for a number of reasons

    *   By hard-coding the base class,  inevitably the Size class would make assumptions about 
        what interfaces (if any) are being implemented, making it far less flexible.

    *   A class that wants to inherit code from a number of bases would need to use multiple 
        inheritance, raising a number of problems.   For example virtual inheritance is needed
        to allow dynamic_cast<> to work correctly.   However virtual inheritance is quite 
        inefficient on space.

    *   When multiple inheritance is used, the Serialise() function won't chain up automatically.

    *   The mixins can be placed in a "library" which contains nothing but headers, avoiding any
        assumptions about deployment of DLLs,  binary compatibility issues.

    *   Someone may subsequently want float members for the width and height.  If the Size
        class is already a template mixin, then additional parameterisation is trivial to add.  By
        contrast, making the Size class a template class for the first time means it needs to be moved
        from a cpp into a header, so this change brings about far more upheaval.
*/
namespace Interfaces1
{
    /* 
    Test that illustrates polymorphic binding to methods on classes that are non-virtual and 
    not written with that binding in mind.  In this case a Circle and a Rectangle class are written
    in standard C++ and then they are coerced into an IShape interface on which polymorphic calls 
    can be made.
    */
    $interface IShape
    {
        ceda::float64 GetArea() const;
        ceda::float64 GetPerimeter() const;
    };

    void DisplayShape(ceda::ptr<IShape> s)
    {
        Tracer() << "  area = " << s->GetArea() << '\n';
        Tracer() << "  perimeter = " << s->GetPerimeter() << '\n';
    }

    const double PI = 3.14159258;

    struct Circle
    {
        Circle() : r(3.0) {}

        ceda::float64 GetArea() const { return PI*r*r; }
        ceda::float64 GetPerimeter() const { return 2*PI*r; }

        ceda::float64 r;
    };

    struct Rectangle
    {
        Rectangle() : l(2.0), w(3.0) {}
        
        ceda::float64 GetArea() const { return l*w; }
        ceda::float64 GetPerimeter() const { return 2*(l+w); }

        ceda::float64 l,w;
    };

    /*
    Output:

        Size of struct Circle = 8
        Size of struct Rectangle = 16
        Size of ptr<IShape> = 16

        circle
            area = 28.2743
            perimeter = 18.8496
        rectangle
            area = 6
            perimeter = 10
    */
    void Run()
    {
        ceda::TraceGroup g("Interfaces example 1");

        Tracer() << "Size of struct Circle = " << sizeof(Circle) << '\n';
        Tracer() << "Size of struct Rectangle = " << sizeof(Rectangle) << '\n';
        Tracer() << "Size of ptr<IShape> = " << sizeof(ceda::ptr<IShape>) << '\n';

        Circle c;
        ceda::ptr<IShape> s = &c;       // Coercion of Circle to IShape
        Tracer() << "\ncircle\n";
        DisplayShape(s);

        Rectangle r;
        s = &r;                         // Coercion of Rectangle to IShape
        Tracer() << "rectangle\n";
        DisplayShape(s);
    }
}

///////////////////////////////////////////////////////////////////////////////////////////////////
/*
Forward declarations
--------------------

An interface can be forward declared like this

    $interface Ix;
    
This allows ptr<Ix> and ptr<const Ix> to be declared, passed around by value and compared using 
== != < <= > >=.  However it doesn't allow for an interface pointer to be dereferenced.

If an interface is forward declared but never actually defined then it isn't registered.
*/
namespace Interfaces2
{
    $interface Ix;
    
    void foo(ceda::ptr<Ix> p1, ceda::ptr<Ix> p2)
    {
        if (p1)                 Tracer() << "p1 is not null\n";
		if (!p1)                Tracer() << "p1 is null\n";
        if (p1 == ceda::null)   Tracer() << "p1 == ceda::null\n";
        if (p1 != ceda::null)   Tracer() << "p1 != ceda::null\n";
        if (p1 == nullptr)      Tracer() << "p1 == nullptr\n";
        if (p1 != nullptr)      Tracer() << "p1 != nullptr\n";
        if (p1 == p2)           Tracer() << "p1 == p2\n";
        if (p1 != p2)           Tracer() << "p1 != p2\n";
        if (p1 < p2)            Tracer() << "p1 < p2\n";
        if (p1 <= p2)           Tracer() << "p1 <= p2\n";
        if (p1 > p2)            Tracer() << "p1 > p2\n";
        if (p1 >= p2)           Tracer() << "p1 >= p2\n";
        
        ceda::ptr<Ix> p;
        ceda::ptr<const Ix> c;

        p = p1;

        // This produces a compiler error because $interface Ix is undefined
        //c = p2;
    }

    /*
    Output:

        p1 is null
        p1 == ceda::null
        p1 == nullptr
        p1 == p2
        p1 <= p2
        p1 >= p2
    */
    void Run()
    {
		ceda::TraceGroup g("Interfaces example 2");
		
		ceda::ptr<Ix> p1;
		ceda::ptr<Ix> p2;
		foo(p1,p2);
    }
}

///////////////////////////////////////////////////////////////////////////////////////////////////
/*
Interface inheritance
---------------------

Interfaces can inherit from each other.  Only DAG structures are permitted.

The following example defines interfaces that form the following inheritance structure

            
                IShape
                /     \
               /       \
      IColouredShape  ICircle 
              \        /
               \      /
            IColouredCircle
            

Let a sub-interface refer to either a directly or indirectly inherited interface.  For example,
the sub-interfaces of IColouredCircle are IShape,IColouredShape,ICircle.

An interface inherits all the methods from its sub-interfaces.  A pointer to an interface can be 
implicit upcast to a pointer to any sub-interface.

Sideways or downwards casting of interface pointers requires a qicast<> but is only supported for 
interfaces that inherit from IObject.

Repeated inheritance is supported, but only indirectly.  The following is not permitted

    $interface Ix {};
    $interface Iy : Ix, Ix {}
*/
namespace Interfaces3
{
    $interface IShape
    {
		ceda::float64 GetArea() const;
		ceda::float64 GetPerimeter() const;
    };

    $interface IColouredShape : IShape
    {
		ceda::int32 GetColour() const;
    };
    
    $interface ICircle : IShape
    {
        ceda::float64 GetRadius() const;
    };

    $interface IColouredCircle : IColouredShape, ICircle
    {
    };

    void TraceShape(ceda::ptr<IShape> s)
    {
        Tracer() << "Shape"
                 << "  A= " << s->GetArea()
                 << "  P= " << s->GetPerimeter()
                 << '\n';
    }

    void TraceCircle(ceda::ptr<ICircle> s)
    {
        Tracer() << "Circle"
                 << "  A= " << s->GetArea()
                 << "  P= " << s->GetPerimeter()
                 << "  r= " << s->GetRadius()
                 << '\n';
    }

    void TraceColouredCircle(ceda::ptr<IColouredCircle> s)
    {
        Tracer() << "Coloured circle"
                 << "  A= " << s->GetArea()
                 << "  P= " << s->GetPerimeter()
                 << "  r= " << s->GetRadius()
                 << "  c= " << s->GetColour()
                 << '\n';
    }
    
    const double PI = 3.14159258;

	struct ColouredCircle
	{
		ColouredCircle() : r(3.0), c(17) {}
		
		ceda::float64 GetArea() const { return PI*r*r; }
		ceda::float64 GetPerimeter() const { return 2*PI*r; }
        ceda::float64 GetRadius() const { return r; }
		ceda::int32 GetColour() const { return c; }

		ceda::float64 r;
		ceda::int32 c;
	};
    
    /*
    Output:

        Shape  A= 28.2743  P= 18.8496
        Circle  A= 28.2743  P= 18.8496  r= 3
        Coloured circle  A= 28.2743  P= 18.8496  r= 3  c= 17
    */
    void Run()
    {
		ceda::TraceGroup g("Interfaces example 3");
		
		ColouredCircle c;
		ceda::ptr<IColouredCircle> s = &c;

		TraceShape(s);
		TraceCircle(s);
		TraceColouredCircle(s);
    }

    // Error - won't compile - directly repeated base interface
    @if (false)
    {
        $interface Ix {};
        $interface Iy : Ix, Ix {};
    }

    // Error - won't compile - can't inherit from undefined base interface
    @if (false)
    {
        $interface Ix;
        $interface Iy : Ix {};
    }

    // todo: This currently compiles.  Should redundant inheritance links be valid?
    @if (false)
    {
        $interface Ix {};
        $interface Iy : Ix {};
        $interface Iz : Ix,Iy {};
    }
}

namespace Interfaces3b
{
	struct IShape
	{
		virtual ceda::float64 GetArea() const = 0;
		virtual ceda::float64 GetPerimeter() const = 0;
	};
	struct IColouredShape : public virtual IShape
	{
		virtual ceda::int32 GetColour() const = 0;
	};
	struct ICircle : public virtual IShape
	{
		virtual ceda::float64 GetRadius() const = 0;
	};
	struct IColouredCircle : 
	    public virtual IColouredShape, 
	    public virtual ICircle
	{
	};
	struct ColouredCircle : public IColouredCircle
	{
		ColouredCircle() : r(3.0), c(17) {}
		
		ceda::float64 GetArea() const 
		{ 
			return 3.14*r*r; 
		}
		ceda::float64 GetPerimeter() const 
		{ 
			return 2*3.14*r; 
		}
		ceda::float64 GetRadius() const 
		{ 
			return r; 
		}
		ceda::int32 GetColour() const 
		{ 
			return c; 
		}
		
		ceda::float64 r;
		ceda::int32 c;
	};

    /*
    Output:

        Size of ColouredCircle = 88
    */
    void Run()
    {
		ceda::TraceGroup g("Interfaces example 3b");
		
		Tracer() << "Size of ColouredCircle = " << sizeof(ColouredCircle) << '\n';
		
		//ColouredCircle c;
		//ceda::ptr<IColouredCircle> s = &c;

		//TraceShape(s);
		//TraceCircle(s);
		//TraceColouredCircle(s);
    }
}

///////////////////////////////////////////////////////////////////////////////////////////////////
/*
Overload resolution and interface inheritance
---------------------------------------------

A derived class inherits the methods from all its sub-interfaces.  There is no hiding rule with 
interface inheritance.  In the example below, Ib::foo(int32) doesn't hide inherited method 
Ia::foo(int16).

Note however that the example would not compile if foo() had the same signature in both 
declarations.  I.e. it is an error for there to be more than one method with the same signature in an
interface, when accounting for all the methods defined in that interface as well as methods 
inherited through its sub-interfaces.

The methods defined directly in an interface, plus all the inherited methods are treated equally
for the purposes of overload resolution.  The standard C++ rules for overload resolution are
employed.  In the example below the following

    p->foo(int16(10));
    
is not ambiguous and calls foo(int16) even though there is an implicit cast from int16 to int32.
*/
namespace Interfaces4
{
    $interface Ia
    {
        void foo(ceda::int16 x);
    };
    
    $interface Ib : Ia
    {
        void foo(ceda::int32 x);
    };
    
    struct X
    {
        void foo(ceda::int16 x) { Tracer() << "foo 16\n"; }
        void foo(ceda::int32 x) { Tracer() << "foo 32\n"; }
    };
    
    /*
    Output:

        foo 16
        foo 32
    */
    void Run()
    {
		ceda::TraceGroup g("Interfaces example 4");
		
		X x;
		ceda::ptr<Ib> p = &x;
		
		p->foo(ceda::int16(10));
		p->foo(ceda::int32(20));
    }

    // Error - won't compile : repeated method with same signature
    @if (false)
    {
        $interface Ix
        {
            void foo();
        };
        
        $interface Iy : Ix
        {
            void foo();
        };
    }
}

///////////////////////////////////////////////////////////////////////////////////////////////////
/*
IObject
-------

Xcpp interfaces should inherit directly or indirectly from IObject in order to gain the following 
features

    *   Support for qicast<> which is an equivalent to dynamic_cast<> for xcpp interfaces.
    
    *   Allow for classes and structs to indicate that they implement the interface in the 
        reflection information
*/
namespace Interfaces5
{
    /*
    The following example defines interfaces as follows

                IObject
                /    \
               /      \
              Ix      Iy
               \      /
                \    /
                  Iz
                  
    It then shows an example of a class C that implements Iz (and hence all the other interfaces as 
    well),  and shows how qicast<> can be used to cast an interface pointer from one interface to
    another.
    */
    
	$interface+ Ix : ceda::IObject
	{
		void foo();
		void cfoo() const;
	};
	
	$interface+ Iy : ceda::IObject
	{
		void bar();
		void cbar() const;
	};
	
	$interface+ Iz : Ix,Iy
	{
	};
	
	$interface+ Iw {};
	
	$struct C isa Iz
	{
        // This declaration inserts all the method prototypes for the given interfaces
        $implementing Ix,Iy;
	};

    void C::foo() { Tracer() << "foo\n"; }
    void C::bar() { Tracer() << "bar\n"; }
    void C::cfoo() const { Tracer() << "cfoo\n"; }
    void C::cbar() const { Tracer() << "cbar\n"; }
    
    @def direct_superinterface(I1,I2) =
    {
		ceda::is_direct_superinterface_of<I1,I2>::value
    }

    @def indirect_superinterface(I1,I2) =
    {
		ceda::is_indirect_superinterface_of<I1,I2>::value
    }

    @def superinterface(I1,I2) =
    {
		ceda::is_superinterface_of<I1,I2>::value
    }
    
    @def assert_superinterface(I1,I2) =
    {
        static_assert( superinterface(I1,I2) );
        static_assert( superinterface(const I1,I2) );
        static_assert( !superinterface(I1,const I2) );
        static_assert( superinterface(const I1,const I2) );
    }

    /*
    Output:

        foo
        bar
        foo
        bar
        cbar
        cfoo
        cbar
        cfoo
        cbar
    */
	void Run()
	{
        /*
               IObject
                /    \
               /      \
              Ix      Iy
               \      /
                \    /
                  Iz
        */
		static_assert( ceda::is_interface<ceda::IObject>::value );
		static_assert( ceda::is_interface<Ix>::value );
		static_assert( ceda::is_interface<Iy>::value );
		static_assert( ceda::is_interface<Iz>::value );
		static_assert( ceda::is_interface<Iw>::value );
		
		static_assert( ceda::is_reflected<ceda::IObject>::value );
		static_assert( ceda::is_reflected<Ix>::value );
		static_assert( ceda::is_reflected<Iy>::value );
		static_assert( ceda::is_reflected<Iz>::value );
		static_assert( ceda::is_reflected<Iw>::value );
		
		static_assert( ceda::is_registered<ceda::IObject>::value );
		static_assert( ceda::is_registered<Ix>::value );
		static_assert( ceda::is_registered<Iy>::value );
		static_assert( ceda::is_registered<Iz>::value );
		static_assert( ceda::is_registered<Iw>::value );

		///////// direct_superinterface

		static_assert( !direct_superinterface(ceda::IObject, ceda::IObject) );
		static_assert( direct_superinterface(ceda::IObject, Ix) );
		static_assert( direct_superinterface(ceda::IObject, Iy) );
		static_assert( !direct_superinterface(ceda::IObject, Iz) );

		static_assert( !direct_superinterface(Ix, ceda::IObject) );
		static_assert( !direct_superinterface(Ix, Ix) );
		static_assert( !direct_superinterface(Ix, Iy) );
		static_assert( direct_superinterface(Ix, Iz) );
		
		static_assert( !direct_superinterface(Iy, ceda::IObject) );
		static_assert( !direct_superinterface(Iy, Ix) );
		static_assert( !direct_superinterface(Iy, Iy) );
		static_assert( direct_superinterface(Iy, Iz) );
		
		static_assert( !direct_superinterface(Iz, ceda::IObject) );
		static_assert( !direct_superinterface(Iz, Ix) );
		static_assert( !direct_superinterface(Iz, Iy) );
		static_assert( !direct_superinterface(Iz, Iz) );
		
		static_assert( direct_superinterface(Ix, Iz) );
		static_assert( direct_superinterface(const Ix, Iz) );
		static_assert( !direct_superinterface(Ix, const Iz) );
		static_assert( direct_superinterface(const Ix, const Iz) );
		

		///////// indirect_superinterface

		static_assert( !indirect_superinterface(ceda::IObject, ceda::IObject) );
		static_assert( !indirect_superinterface(ceda::IObject, Ix) );
		static_assert( !indirect_superinterface(ceda::IObject, Iy) );
		static_assert( indirect_superinterface(ceda::IObject, Iz) );

		static_assert( !indirect_superinterface(Ix, ceda::IObject) );
		static_assert( !indirect_superinterface(Ix, Ix) );
		static_assert( !indirect_superinterface(Ix, Iy) );
		static_assert( !indirect_superinterface(Ix, Iz) );
		
		static_assert( !indirect_superinterface(Iy, ceda::IObject) );
		static_assert( !indirect_superinterface(Iy, Ix) );
		static_assert( !indirect_superinterface(Iy, Iy) );
		static_assert( !indirect_superinterface(Iy, Iz) );
		
		static_assert( !indirect_superinterface(Iz, ceda::IObject) );
		static_assert( !indirect_superinterface(Iz, Ix) );
		static_assert( !indirect_superinterface(Iz, Iy) );
		static_assert( !indirect_superinterface(Iz, Iz) );

		///////// superinterface (reflexive and transitive closure over direct and indirect superinterfaces)
		
		assert_superinterface(ceda::IObject, ceda::IObject)
		assert_superinterface(ceda::IObject, Ix)
		assert_superinterface(ceda::IObject, Iy)
		assert_superinterface(ceda::IObject, Iz)

		static_assert( !superinterface(Ix, ceda::IObject) );
		assert_superinterface(Ix, Ix)
		static_assert( !superinterface(Ix, Iy) );
		assert_superinterface(Ix, Iz)
		
		static_assert( !superinterface(Iy, ceda::IObject) );
		static_assert( !superinterface(Iy, Ix) );
		assert_superinterface(Iy, Iy)
		assert_superinterface(Iy, Iz)
		
		static_assert( !superinterface(Iz, ceda::IObject) );
		static_assert( !superinterface(Iz, Ix) );
		static_assert( !superinterface(Iz, Iy) );
		assert_superinterface(Iz, Iz)
		
		ceda::TraceGroup g("Interfaces example 5");
		
		C c;
		{
		    ceda::ptr<Iz> pz = &c;
    		
		    pz->foo();
		    pz->bar();
    		
		    ceda::ptr<Ix> px = &c;
		    px->foo();
    		
		    // qicast<> can be used to cast to any other supported interface
		    ceda::ptr<Iy> py = ceda::qicast<Iy>(px);
		    py->bar();

		    ceda::ptr<const Iy> cpy = ceda::qicast<const Iy>(px);
		    cpy->cbar();
    		
            // Casting to an interface that is not implemented by the object will return null.
		    cxAssert(ceda::qicast<Iw>(pz) == ceda::null);
        }

		{
		    ceda::ptr<const Iz> pz = &c;
    		
		    pz->cfoo();
		    pz->cbar();
    		
		    ceda::ptr<const Ix> px = &c;
		    px->cfoo();
    		
		    // qicast<> can be used to cast to any other supported interface
		    ceda::ptr<const Iy> py = ceda::qicast<const Iy>(px);
		    py->cbar();
    		
            // Casting to an interface that is not implemented by the object will return null.
		    cxAssert(ceda::qicast<const Iw>(pz) == ceda::null);
        }
        
        {
		    ceda::ptr<const Iz> pz = &c;
		    
		    // error C2440: 'initializing' : cannot convert from 'ceda::ptr<T>' to 'void *' 
		    //void* pv = pz;
		    
		    const void* pv = pz;
		    
		    cxAssert(pv = &c);
        }            
	}
}

///////////////////////////////////////////////////////////////////////////////////////////////////
/*
Moonlighting

On first inspection of the technique it could be regarded as a hack.  Giving it the fancy name of
moonlighting draws attention to its purpose.  The idea is actually justifiable.

When an instance of a class X is coerced into a ptr<T> for some xcpp interface T,  there is a check
at compile time for whether X contains all the methods specified in T.  The coercion process is not
type intrusive in the sense that the definition of X may not mention or know about T at all.

The moonlighting technique can be used when X doesn't actually have the methods specified in T and 
yet we can make sense of the idea for X to in fact implement T.  In most languages this would 
require the adapter design pattern,  involving a separate and distinct object that implements T
and forwards calls into the instance of X as required.

By contrast, the moonlighting technique is very enconomical because it doesn't require a separate
adapter object.  In fact it can even lead to complete inlining so that the polymorphic call through
at interface pointer does require subsequent delegation at all.

The trick involves inheriting a class (let's call it M) from X.  It is important that M doesn't add
any additional state.  Rather it simply adds additional methods,  allowing it to implement all the
methods in T.  This provides the freedom to rename methods, etc.  Note that methods in M can hide 
methods in base class X.  This allows M to even "fiddle" with methods that already have the right 
name and signature.

After defining M, it is a simple manner to reinterpret cast a given pointer to an X as a pointer
to an M before it is coerced into a ptr<T>
*/
namespace Moonlighting1
{
	// This example demonstrates xstring moonlighting as a button listener, although this is
	// a bizarre example it shows how moonlighting can be used to augment a type's functionality
	// in such a way that it can fulfil some other contract that the plain type (in this case
	// xstring) could not fulfil on its own.
	
	$interface IButtonHandler
	{
		void OnButtonPressed();
	};

    /*
    Output:

        Before pressing button, str = aaa
        After pressing button, str = aaax
    */
	void Run()
	{
		ceda::TraceGroup g("Moonlighting example 1");
	
		// Struct M inherits from xstring but doesn't add any additional state. It implements 
		// the method OnButtonPressed() in order to allow a xstring to be coerced into a 
		// ptr<IButtonHandler>
		struct M : public ceda::xstring 
		{ 
		    void OnButtonPressed() { push_back('x'); } 
		};
		
		ceda::xstring str = "aaa";
		
		// Reinterpret the string as an M to allow it to be coerced into a ptr<IButtonHandler>
		ceda::ptr<IButtonHandler> b( (M*)&str );
		
		Tracer() << "Before pressing button, str = " << str << '\n';
		b->OnButtonPressed();
		Tracer() << "After pressing button, str = " << str << '\n';
	}
}

///////////////////////////////////////////////////////////////////////////////////////////////////
/*
Moonlighting to wire up CDPlayer
--------------------------------

This example shows how a CD Player can internally wire its play and stop buttons to its 
Play() and Stop() methods.

This is a practical illustration of the moonlighting technique.  It is well suited to allowing a 
client to privately implement an interface in order to receive notifications as part of its 
"internal wiring".

Java employs anonymous inner classes.  C# uses delegates.  The technique ilustrated here is very 
efficient because it avoids additional heap allocations.
*/
namespace Moonlighting2
{
	///////////////////////////////////////////////////////////////////////////////////////////////
	// Button.h

    // A client implements this interface in order to receive a notification that a button has 
    // been pressed.
	$interface IButtonListener
	{
		void OnButtonPressed();
	};
	
	class Button
	{
	public:
		// Client calls SetHandler() in order to set the handler that receives the notification 
		// that the button has been pressed
		void SetHandler( ceda::ptr<IButtonListener> handler ) 
		{ 
		    m_handler = handler; 
		}
		
        // It is assumed OnMouseClicked() is called when the user clicks the mouse button while the
        // mouse cursor is over the button
		void OnMouseClicked() 
		{ 
        	// Send the notification to the client that the button has been pressed
		    m_handler->OnButtonPressed(); 
		}
	private:
		ceda::ptr<IButtonListener> m_handler;
	};

	///////////////////////////////////////////////////////////////////////////////////////////////
	// CDPlayer.cpp

    class CDPlayer
    {
    public:
        CDPlayer()
        {
            // Constructor of the CDPlayer wires up the button notifications to the Play() and
            // Stop() methods.
            
            // The moonlighting technique involves inheriting from the CDPlayer class without 
            // adding additional state, in order to implement IButtonListener.
            // Note how the notification binds to the Play() member function, and it can pass a 
            // parameter into the function.
            struct B1 : public CDPlayer { void OnButtonPressed() { Play(5); } };
            m_playButton.SetHandler((B1*)this);

            // Inherit from CDPlayer in order to implement IButtonListener.  Note how the
            // notification binds to the Stop() member function.
            struct B2 : public CDPlayer { void OnButtonPressed() { Stop(); } };
            m_stopButton.SetHandler((B2*)this);
        }

        void Play(int speed)
        {
            Tracer() << "CD Player Playing with speed = " << speed << '\n';
        }

        void Stop()
        {
            Tracer() << "CD Player Stopped\n";
        }

        void Test()
        {
            m_playButton.OnMouseClicked();
            m_stopButton.OnMouseClicked();
        }

    private:
        Button m_playButton;
        Button m_stopButton;
    };

    /*
    Output:

        CD Player Playing with speed = 5
        CD Player Stopped
    */
	void Run()
	{
		ceda::TraceGroup g("Moonlighting example 2");
		CDPlayer p;
		p.Test();
	}	
}

///////////////////////////////////////////////////////////////////////////////////////////////////
/*
Interface properties
--------------------

In the following example interface Ix declares an abstract int32 property named v. 

	$interface Ix
	{
	    int32 v;
	};

This is syntactic sugar for the following

	$interface Ix
	{
	    int32 Getv() const;
	    void Setv(int32 v);
	};
	
The prefix 'Get' and 'Set' is prepended to the property name.
*/
namespace InterfaceProperty1
{
	$interface Ix
	{
	    ceda::int32 v;
	};
	
	$struct Cx
	{
        ceda::int32 Getv() const { return val; }
        void Setv(ceda::int32 v) { val = v; }
        
        ceda::int32 val;
	};

    /*
    Output:

        p->v = 5
        p->v = 10
    */
	void Run()
	{
		ceda::TraceGroup g("Interface properties example 1");
		
		Cx c;
		ceda::ptr<Ix> p = &c;
		
		p->Setv(5);
		Tracer() << "p->v = " << p->Getv() << '\n';
		
		// Calls Setv()
		p->v = 10;
		
		// Calls Getv()
		Tracer() << "p->v = " << p->v << '\n';
	}
}

///////////////////////////////////////////////////////////////////////////////////////////////////
/*
Interface const properties
---------------------------

In the following example interface Ix declares an abstract const int32 property named v.  The const
modifier means that the property can be read but not modified.

	$interface Ix
	{
	    const int32 v;
	};
	
This is syntactic sugar for the following

	$interface Ix
	{
	    int32 Getv() const;
	};
	
The prefix 'Get' is prepended to the property name.
*/
namespace InterfaceConstProperty
{
	$interface Ix
	{
	    const ceda::int32 v;
	};
	
	$struct Cx
	{
        Cx() : val(100) {}
        
        ceda::int32 Getv() const { return val; }
        ceda::int32 val;
	};

    /*
    Output:

        p->v = 100
    */
	void Run()
	{
		ceda::TraceGroup g("Interface const property");
		
		Cx c;
		ceda::ptr<Ix> p = &c;
		
		// Uncommenting this causes a compiler error
		// error C2679: binary '=' : no operator found which takes a right-hand operand of type 'int'
		//p->v = 10;
		
		// Calls Getv()
		Tracer() << "p->v = " << p->v << '\n';
	}
}

///////////////////////////////////////////////////////////////////////////////////////////////////
/*
Interface vector properties
---------------------------

In the following example interface Ix declares an abstract xvector<float64> property named L.  

	$interface Ix
	{
	    xvector<float64> L;
	};
	
This is syntactic sugar for the following

	$interface Ix
	{
        int32 GetLSize() const;
        void DeleteFromL(int32 i1,int32 i2);
        void RecordExtractFromL(int32 si1,int32 si2,xvector<float64>& dst,int32 di);
        void InsertIntoL(int32 di,xvector<float64>& src,int32 si1,int32 si2);
        float64 GetLElement(int32 i) const;
        void SetLElement(int32 i,float64 e);
	};
*/
@if (false)
{
namespace InterfaceVectorProperty
{
	$interface Ix
	{
	    ceda::xvector<ceda::float64> L;
	};
	
	$struct Cx
	{
        ceda::int32 GetLSize() const
        {
            return L_.size();
        }
        void DeleteFromL(ceda::int32 i1, ceda::int32 i2)
        {
            L_.erase(L_.begin()+i1, L_.begin()+i2);
        }
        void RecordExtractFromL(ceda::int32 si1, ceda::int32 si2, ceda::xvector<ceda::float64>& dst, ceda::int32 di)
        {
        }
        void InsertIntoL(ceda::int32 di,ceda::xvector<ceda::float64>& src,ceda::int32 si1, ceda::int32 si2)
        {
        }
        ceda::float64 GetLElement(ceda::int32 i) const
        {
            return L_[i];
        }
        void SetLElement(ceda::int32 i, ceda::float64 e)
        {
            L_[i] = e;
        }
        
        ceda::xvector<ceda::float64> L_;
    };

    void Run()
    {
        ceda::TraceGroup g("Interface vector property");

        Cx c;
        ceda::ptr<Ix> p = &c;

        // todo: demonstrate all the usage
        int len = p->size();
    }
}
}

///////////////////////////////////////////////////////////////////////////////////////////////////
/*
Interface delegator mixins
--------------------------

For every interface definition, xcpp generates an associated delegator mixin.

For example, for the interface Ix defined as follows

    $interface Ix
    {
        ceda::float64 foo(ceda::float64 v);
    };

the system automatically generates the following mixin 

    $mixin IxDelegatorMixin
    {
        ceda::float64 foo(ceda::float64 v) { return GetIx().foo(v); }
    };
*/
namespace InterfaceDelegatorMixin
{
    $interface Ix
    {
        ceda::float64 foo(ceda::float64 v);
    };

    struct C
    {
        ceda::float64 foo(ceda::float64 v)
        {
            return v*v;
        }
    };

    $struct X :
        mixin 
        [
            // Declare member c
            {
                C c;
            }

            // Delegate implementation of Ix to member c.
            {
                // Method 1
                C& GetIx() { return this->c; }

                // Method 2
                //Ix GetIx() { return *ptr<Ix>(&c); }

                // Method 3 : no good - crashes!
                //Ix& GetIx() { return *ptr<Ix>(&c); }
            }
            IxDelegatorMixin
        ]
    {
    };

    /*
    Output:

        foo(10) = 100
    */
    void Run()
    {
        ceda::TraceGroup g("Interface delegator mixins example");

        X x;
        ceda::ptr<Ix> p = &x;

        Tracer() << "foo(10) = " << p->foo(10) << '\n';
    }
}

namespace ReflectedInterfacePtrs
{
    $interface+ Ix
    {
        ceda::ptr<Ix> f1(ceda::ptr<Ix> p);
    };
    
    $struct+ Cx
    {
        $ceda::ptr<Ix> f2(ceda::ptr<Ix> p) { return p; }
    };
    
    $function+ ceda::ptr<Ix> f3(ceda::ptr<Ix> p)
    {
        return p;
    }
}

namespace ReflectedPrivateInterface
{
    // There is no '+' modifier, which normally means Ix is not exported, reflected or registered
    // However <<reflect>> means Ix is reflected, so GetReflectedInterface<Ix> can be used. However
    // Ix is not registered in the reflection registry.
    $interface Ix <<reflect>>
    {
    };

    /*
    Output:

        GetReflectedInterface<Ix>() succeeded
        TryFindReflectedInterfac() failed
    */
    void Run()
    {
        ceda::TraceGroup g("Reflected private interface");

        // GetReflectedInterface succeeds because Ix has been reflected
        const ceda::ReflectedInterface& ri = ceda::GetReflectedInterface<Ix>();
        
        ceda::xstring name = "ReflectedPrivateInterface::Ix";
        
        cxAssert(ri.GetName() == name);
        Tracer() << "GetReflectedInterface<Ix>() succeeded\n";
        
        // TryFindReflectedInterface fails because Ix has not been registered
        const ceda::ReflectedInterface* fri = ceda::TryFindReflectedInterface(name.c_str());
        cxAssert(!fri);
        Tracer() << "TryFindReflectedInterfac() failed\n";
    }
}

/*
If a $class/$struct uses 'isa' with an interface that doesn't subtype IObject then warning W1003
is generated.  This shouldn't be regarded as a suggestion of a faulty design (the warning only 
serves as a reminder that interfaces that subtype IObject provide some convenient functionality 
such as the ability to qicast between the implemented interfaces.
*/
namespace IsaWithNonIObjectInterfaces
{
    $interface+ I1
    {
    };
    
    $warning(push; disable: 1003)

    // warning W1003 : $interface+ IsaWithNonIObjectInterfaces::I1 doesn't inherit from IObject
    $class+ X1 isa I1
    {
    };
    
    $warning(pop)

    $interface+ I2 : ceda::IObject
    {
    };
    
    $class+ X2 isa I2
    {
    };
    
    struct V : public ceda::IObjectVisitor
    {
        V() : obj(NULL) {}
        
        virtual void VisitObject(ceda::ptr<const ceda::IObject> object)
        {
            Tracer() << "Visiting object " << object << '\n';
            obj = object.self();
        }
        virtual void VisitEvictableObject(ceda::ptr<const ceda::IObject>& object) {}
        
        const void* obj;
    };
    
    /*
    Output:
        
        Visiting object IsaWithNonIObjectInterfaces::X2:000000000021F760
    */
    void Run()
    {
        ceda::TraceGroup g("IsaWithNonIObjectInterfaces");
        
        V v;
        ceda::IObjectVisitor& ov = v;
        
        X1 x1;
        ceda::ptr<I1> p1 = &x1;
        
        ov << p1;        // Compiles without error even though I1 isn't a subinterface of IObject
        
        cxAssert(v.obj == NULL);

        X2 x2;
        ceda::ptr<I2> p2 = &x2;
        ov << p2;
        cxAssert(v.obj == &x2);
    }
}

/*
If a $class/$struct uses 'isa' with an interface that isn't reflected then warning W1013
is generated.  This shouldn't be regarded as a suggestion of a faulty design (the warning only 
serves as a reminder that non-reflected interfaces don't contribute to an implementation of
QueryInterface, which is generated if and only if the $class/$struct/$adt implements IObject)
*/
namespace IsaWithNonReflectedInterfaces
{
    $interface+ I1 : ceda::IObject
    {
    };

    $warning(push; disable: 1007 1013)

    // warning W1007 : $interface IsaWithNonReflectedInterfaces::I2 subtypes IObject but isn't reflected
    $interface I2 : I1
    {
    };
    
    // warning W1013 : $interface IsaWithNonReflectedInterfaces::I2 not reflected
    $class X1 isa I2
    {
    };
    
    $warning(pop)

    void Run()
    {
        ceda::TraceGroup g("IsaWithNonReflectedInterfaces");
        
        X1 x1;
        
        // Since X1 isa I2 and I2 subtypes IObject,  the IObject methods are generated on X1.
        ceda::ptr<ceda::IObject> p = &x1;
        
        // X1 is not reflected so GetReflectedClass() returns NULL
        cxAssert(!p->GetReflectedClass());
        
        // Even though I2 isn't reflected, the generated implementation of QueryInterface accounts 
        // for any reflected superinterfaces of I2 (so in this case qicast to IObject and I1 is 
        // supported).
        cxAssert(ceda::qicast<ceda::IObject>(p) == p);
        cxAssert(ceda::qicast<I1>(p) == p);
        
        // qicast<I2> unavailable because I2 is not reflected
        //ceda::qicast<I2>(p);
    }
}

namespace Qccast
{
    // warning W1003 : isa on $interface+ Qccast::I2 doesn't inherit from IObject
    $warning(push; disable: 1003)
    
    $interface+ I1 : ceda::IObject
    {
    };

    $interface+ I2
    {
    };

    $class X1 isa I1, I2
    {
        ceda::int32 v;
    };

    $class+ X2 isa I1, I2
    {
        ceda::float32 v;
    };
    
    $warning(pop)

    /*
    Output:

        p1 as X1 v = 100
        p2 as X1 v = 1103626240
        p2 as X2 v = 25

        p1 as X1 v = 100
        p2 as X1 v = 1103626240
        p2 as X2 v = 25
    */        
    void Run()
    {
        ceda::TraceGroup g("qccast");
        
        X1 x1;
        x1.v = 100;

        X2 x2;
        x2.v = 25;

        {
            ceda::ptr<I1> p1 = &x1;
            ceda::ptr<I1> p2 = &x2;
            
            Tracer() << "p1 as X1 v = " << ceda::qccast<X1>(p1)->v << '\n';
            
            // This attempt at qicast<X2>(p1) trips an assertion because 
            //      1)  p1 doesn't actually point at an object of type X2
            //      2)  p1 is an interface of type I1 which subtypes IObject
            //      3)  X2 is reflected
            //Tracer() << "p1 as X2 v = " << ceda::qccast<X2>(p1)->v << '\n';
            
            // This invalid qccast silently succeeds, and prints a weird value
            Tracer() << "p2 as X1 v = " << ceda::qccast<X1>(p2)->v << '\n';
            
            Tracer() << "p2 as X2 v = " << ceda::qccast<X2>(p2)->v << '\n' << '\n';
        }
        
        {
            ceda::ptr<const I1> p1 = &x1;
            ceda::ptr<const I1> p2 = &x2;
            
            // Compile time error : qccast cannot cast away constness
            // ceda::qccast<X1>(p1);
            
            Tracer() << "p1 as X1 v = " << ceda::qccast<const X1>(p1)->v << '\n';
            
            // This attempt at qicast<const X2>(p1) trips an assertion because 
            //      1)  p1 doesn't actually point at an object of type X2
            //      2)  p1 is an interface of type I1 which subtypes IObject
            //      3)  X2 is reflected
            //Tracer() << "p1 as X2 v = " << ceda::qccast<const X2>(p1)->v << '\n';
            
            // This invalid qccast silently succeeds, and prints a weird value
            Tracer() << "p2 as X1 v = " << ceda::qccast<const X1>(p2)->v << '\n';
            
            Tracer() << "p2 as X2 v = " << ceda::qccast<const X2>(p2)->v << '\n';
        }
    }
}

///////////////////////////////////////////////////////////////////////////////////////////////////
namespace Interfaces
{
    void Run()
    {
        Interfaces1::Run();
        Interfaces2::Run();
        Interfaces3::Run();
        Interfaces3b::Run();
        Interfaces4::Run();
        Interfaces5::Run();
        Moonlighting1::Run();
        Moonlighting2::Run();
        InterfaceProperty1::Run();
        InterfaceConstProperty::Run();
        //InterfaceVectorProperty::Run();
        InterfaceDelegatorMixin::Run();
        ReflectedPrivateInterface::Run();
        IsaWithNonIObjectInterfaces::Run();
        IsaWithNonReflectedInterfaces::Run();
        Qccast::Run();
    }
}