Question

I'm currently working on a [OMG13] (s. below) compliant C++11 partial facade for adapting a legacy (C++)ORB; "partial" in the sense of just server-side, no DII, no OBV etc - thus the very basic stuff only.

[OMG13] has in 6.25.6 Inheritance-Based Interface Implementation

Implementation must be derived from a generated base class based on the OMG IDL interface definition. The generated base classes are known as skeleton classes, and the derived classes are known as implementation classes. Each operation of the interface has a corresponding virtual member function declared in the skeleton class.

[emphasis mine]

That, if taken literally, implies that, for an interface A defined in the idl, A_impl shall be a descendant of A_skel

class A_impl : /* whatever, likely public */  A_skel {
    /**/
};

But the snippets given in 6.25.6 tell otherwise

// C++
class A_skel : public virtual CORBA::servant_traits<A>::base_type { ... };
// C++
class A_impl: public virtual CORBA::servant_traits<A>::base_type { ... };

So, according to the snippets, A_impl and A_skel are siblings, descending from the same ancestor.


It's not trivial to decide what to do, because the standard for the former, C++ prior to C++11, mapping [OMG12], has 5.40.3 Inheritance-Based Interface Implementation

Implementation classes can be derived from a generated base class based on the OMG IDL interface definition. The generated base classes are known as skeleton classes, and the derived classes are known as implementation classes.

so it is "can" not "must" for C++, prior to C++11, mapping, and the snippets given in are consistent with this "can"

class POA_A : public virtual PortableServer::ServantBase 
{
    /* [...] */
}

/* [...] */

class A_impl : public POA_A
{
   /* [...] */
};

and that is also what the legacy ORB, I work with, infrastructure is built for (aside of also offering [OMG12]-compliant delegation-based implementation).


So - how to relate _skel and _impl in my little c++11-compliance ORB facade to be [OMG13]-compliant and hardening impl code against possible refactoring of that part of [OMG13]?

One could e.g. consider deriving _impls from an CRTP-style inheritance-multiplexing class:

struct Snippet_Reading{};
struct Prose_Reading{};

namespace mock {

    class IA{}; 

    // impl specific, not important here  
    template<class Ifc>
    struct LoremIpsum {}; 


    template<class Ifc>
    class POA_Delegator {
         // impl specific, not important here  
    };

    namespace CORBA {
        template<class Ifc>
        struct servant_traits {
            /// @TODO meditate how to implement that
            typedef LoremIpsum<Ifc> base_type;
        };
    }
} 

namespace detail {
    using namespace mock;

    template<typename Reading, class Ifc>
    class Base {};

    template<class Ifc>
    class Base<Prose_Reading, Ifc> : public virtual POA_Delegator<Ifc> {};

    template<class Ifc>
    class Base<Snippet_Reading, Ifc> : public virtual CORBA::servant_traits<Ifc>::base_type {};
}

#if defined(PROSE_READING)
    template <class Ifc>
    using Base = detail::Base<Prose_Reading, Ifc>;
#elif  defined(SNIPPET_READING)
    template <class Ifc>
    using Base = detail::Base<Snippet_Reading, Ifc>;
#else
    #error Oh My Goodness! Don't know how to interpret OMG's IDL to C++11 Mapping!
#endif 


class IA_impl : public virtual Base<mock::IA> {};


int main() {}

but this yields not exactly a standard-compliant implementor's interface.

References

[OMG12] OMG C++ Language Mapping. OMG, 2012. http://www.omg.org/spec/CPP/1.3

[OMG13] OMG. C++11 Language Mapping. OMG, 2013. http://www.omg.org/spec/CPP11/

Was it helpful?

Solution

CORBA::servant_traits::base_type should resolve to A_skel at compile time. The user doesn't really see A_skel, that is just an implementation detail. The user defined A_impl than just derived from the CORBA::servant_traits::base_type trait.

There is an error in 6.26.6 as you pointed out. The skeleton classes should derive from each other, not from the traits, so it should be as below, also C_skel is lacking.

// C++
class A_skel : public virtual PortableServer::ServantBase {};
class B_skel : public virtual A_skel {};
class C_skel : public virtual A_skel {};
class D_skel : public virtual B_skel, public virtual C_skel {};

For the draft V1.1 mapping see http://osportal.remedy.nl. We could also assist with your challenge, feel free to contact me directly.

Could you report a formal issue to the OMG for the example in 6.26.2 so that we can resolve that in the V1.2 version of the spec

OTHER TIPS

In response to Johnny Willemsen's answer:

OK, let's tie the pieces together:

The standard demands

class A_impl: public virtual CORBA::servant_traits<A>::base_type { ... };

and if this

CORBA::servant_traits::base_type should resolve to A_skel at compile time.

shall hold for A_skel defined this way

class A_skel : public virtual PortableServer::ServantBase {};

then there must be a specialization for A of template<T>struct CORBA::servant_traits, so I take it, the standard shall imply this sort of dependencies:

class A {
  public:
    virtual long foo() = 0;
};

namespace mock {

    namespace CORBA {
        template<class Ifc>
        struct servant_traits { /* ? */};
    }

    namespace PortableServer {
        class ServantBase { /* ... */};
    }
} 

using namespace mock;

class A_skel : public virtual PortableServer::ServantBase {
    virtual long foo() = 0;
};

namespace mock {
    namespace CORBA {
        template<>
        struct servant_traits<A> {
            typedef A_skel base_type;
            // ...
        };
    }
}    

class A_impl : public virtual CORBA::servant_traits<A>::base_type {
  public:
    virtual long foo() {
        return 42;
    }
};

int main() {}

Do I get this right?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top