Advertisement
novacisko

IInterface in LightSpeed

Nov 21st, 2011
259
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.52 KB | None | 0 0
  1. #pragma once
  2. #ifndef _INTERFACE_H__lightspeed_ondra_2010_
  3. #define _INTERFACE_H__lightspeed_ondra_2010_
  4. #include "../base/typeinfo.h"
  5. #include "memory/pointer.h"
  6. #include "exceptions/exception.h"
  7.  
  8.  
  9. namespace LightSpeed {
  10.  
  11.  
  12.     ///Helps to access other interface in the object
  13.     /**
  14.      * Every object can implement more interfaces than one. One of interfaces
  15.      * are used to carry instance of the object. This interface is called main.
  16.      *
  17.      * Main interface should extends this interface IInterface, which supplies
  18.      * function to access other interfaces.
  19.      *
  20.      * The most common way to access other interface is to use dynamic_cast operator.
  21.      * But this require, that object implements every function of all exported
  22.      * interfaces. It is very hard to access delegated interface or make proxy
  23.      * object.
  24.      *
  25.      * Interface IInterface allows pass requests through proxies using function proxyInterface.
  26.      * In default configuration every class which inherits the IInterface implements this
  27.      * function using dynamic_cast to the itself, so interface supplies
  28.      * dynamic_cast as expected. But proxy can redefine that function and
  29.      * pass request to the other objects. There is only one condition, that
  30.      * other objects must meet. They have to implement IInterface too.
  31.      *
  32.      * @see getIfc, getIfcPtr
  33.      *
  34.      */
  35.     class IInterface {
  36.     public:
  37.  
  38.  
  39.         ///Retrieves interface pointer
  40.         /**
  41.          * @tparam Ifc use name of interface (as type) which you require. You
  42.          * should use interface, not name of implementating class, even if it
  43.          * will work.
  44.          * @return pointer to interface, or nil in case, that interface is not implemented
  45.          */
  46.         template<typename Ifc>
  47.         Pointer<Ifc> getIfcPtr();
  48.         ///Retrieves interface pointer
  49.         /**
  50.          * @tparam Ifc use name of interface (as type) which you require. You
  51.          * should use interface, not name of implementation class, even if it
  52.          * will work.
  53.          * @return pointer to interface, or nil in case, that interface is not implemented
  54.          */
  55.         template<typename Ifc>
  56.         Pointer<const Ifc> getIfcPtr() const;
  57.  
  58.         ///Retrieves interface reference
  59.         /**
  60.          * @tparam Ifc use name of interface (as type) which you require. You
  61.          * should use interface, not name of implementation class, even if it
  62.          * will work.
  63.          * @return reference to the interface
  64.          * @exception InterfaceNotImplementedException thrown when interface is not implemented.
  65.          *
  66.          * @note use this function when you are sure, that interface must be implemented. You
  67.          * don't need to test return value and exception guards application against to
  68.          * dereferencing of NULL pointer
  69.          */
  70.         template<typename Ifc>
  71.         Ifc &getIfc();
  72.         ///Retrieves interface reference
  73.         /**
  74.          * @tparam Ifc use name of interface (as type) which you require. You
  75.          * should use interface, not name of implementation class, even if it
  76.          * will work.
  77.          * @return reference to the interface
  78.          * @exception InterfaceNotImplementedException thrown when interface is not implemented.
  79.          *
  80.          * @note use this function when you are sure, that interface must be implemented. You
  81.          * don't need to test return value and exception guards application against to
  82.          * dereferencing of NULL pointer
  83.          */
  84.         template<typename Ifc>
  85.         const Ifc &getIfc() const;
  86.  
  87.  
  88.         ///dtor
  89.         virtual ~IInterface() {}
  90.     protected:
  91.  
  92.  
  93.         ///Interface which allows to access to the request
  94.         class IInterfaceRequest {
  95.         public:
  96.  
  97.             ///Tries to convert pointer to required interface
  98.             /**
  99.              * @param ifc pointer to object to convert
  100.              * @return pointer to interface, or NULL, when impossible
  101.              */
  102.             virtual void *getInterface(IInterface *ifc) = 0;
  103.             ///Tries to convert pointer to required interface
  104.             /**
  105.              * @param ifc pointer to object to convert
  106.              * @return pointer to interface, or NULL, when impossible
  107.              */
  108.             virtual const void *getInterface(const IInterface *ifc) const = 0;
  109.             ///Retrieves TypeInfo object containing information about requested type
  110.             /**
  111.              * @return TypeInfo object containing information about requested type
  112.              */
  113.             virtual TypeInfo getType() const = 0;
  114.         };
  115.  
  116.         template<typename Ifc>
  117.         class IfcProxy;
  118.  
  119.         ///Calls to proxy request into delegated object
  120.         /**
  121.          * @param p reference to request
  122.          * @return pointer to interface, or NULL when impossible
  123.          *
  124.          * @note Default implementation calls IInterfaceRequest::getInterface() to this
  125.          */
  126.         virtual void *proxyInterface(IInterfaceRequest &p) {
  127.             return p.getInterface(this);
  128.         }
  129.         ///Calls to proxy request into delegated object
  130.         /**
  131.          * @param p reference to request
  132.          * @return pointer to interface, or NULL when impossible
  133.          *
  134.          * @note Default implementation calls IInterfaceRequest::getInterface() to this
  135.          */
  136.         virtual const void *proxyInterface(const IInterfaceRequest &p) const {
  137.             return p.getInterface(this);
  138.         }
  139.  
  140.     };
  141.  
  142.     class InterfaceNotImplementedException;
  143.  
  144.  
  145.  
  146.  
  147. template<typename Ifc>
  148. class IInterface::IfcProxy: public IInterface::IInterfaceRequest {
  149. public:
  150.  
  151.     virtual void *getInterface(IInterface *ifc) {
  152.         return dynamic_cast<Ifc *>(ifc);
  153.     }
  154.     virtual const void *getInterface(const IInterface *ifc) const {
  155.         return dynamic_cast<const Ifc *>(ifc);
  156.     }
  157.     virtual TypeInfo getType() const {
  158.         return typeid(Ifc);
  159.     }
  160. };
  161.  
  162.  
  163.  
  164. template<typename Ifc>
  165. Pointer<Ifc> IInterface::getIfcPtr() {
  166.     IfcProxy<Ifc> proxy;
  167.     return reinterpret_cast<Ifc *>(proxyInterface(proxy));
  168. }
  169. template<typename Ifc>
  170. Pointer<const Ifc> IInterface::getIfcPtr() const {
  171.     IfcProxy<Ifc> proxy;
  172.     return reinterpret_cast<const Ifc *>(proxyInterface(proxy));
  173. }
  174.  
  175. class InterfaceNotImplementedException: public Exception {
  176. public:
  177.     LIGHTSPEED_EXCEPTIONFINAL;
  178.  
  179.     InterfaceNotImplementedException(const ProgramLocation &loc, TypeInfo ifcReq, TypeInfo object)
  180.         :ifcReq(ifcReq),object(object) {}
  181.  
  182.     TypeInfo getRequestedInterface() const {return ifcReq;}
  183.     TypeInfo getObject() const {return object;}
  184.  
  185.     static const char *msgText;
  186. protected:
  187.     TypeInfo ifcReq,object;
  188.  
  189.     void message(ExceptionMsg &msg) const {
  190.         msg(msgText) << object.name() << ifcReq.name();
  191.     }
  192. };
  193.  
  194. template<typename Ifc>
  195. Ifc &IInterface::getIfc() {
  196.     Ifc *x = getIfcPtr<Ifc>();
  197.     if (x == 0) {
  198.         throw InterfaceNotImplementedException(THISLOCATION, TypeInfo(typeid(Ifc)), TypeInfo(typeid(*this)));
  199.     }
  200.     return *x;
  201. }
  202. template<typename Ifc>
  203. const Ifc &IInterface::getIfc() const {
  204.     const Ifc *x = getIfcPtr<Ifc>();
  205.     if (x == 0) {
  206.         throw InterfaceNotImplementedException(THISLOCATION, TypeInfo(typeid(Ifc)), TypeInfo(typeid(Ifc)));
  207.     }
  208.     return *x;
  209.  
  210. }
  211.  
  212.  
  213. }  // namespace LightSpeed
  214.  
  215.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement