В настоящее время я работаю над [OMG13] (см. Ниже) совместимым частичным фасадом C ++ 11 для адаптации устаревшего (C ++) ORB; «частичный» в смысле только серверной части, без DII, без OBV и т. д. — таким образом, только очень простые вещи.
[OMG13] имеет в 6.25.6 Реализация интерфейса на основе наследования[акцент мой]Реализация должна быть получена из сгенерированного базового класса основанный на
определение интерфейса OMG IDL. Сгенерированные базовые классы известны
как скелет классы, и производные классы известны как
классы реализации. Каждая операция интерфейса имеет
соответствующая виртуальная функция-член, объявленная в классе скелета.
Это, если понимать буквально, подразумевает, что для интерфейса A, определенного в idl, A_impl должен быть потомком A_skel
class A_impl : /* whatever, likely public */ A_skel {
/**/
};
Но фрагменты, приведенные в 6.25.6 сказать иначе
// C++
class A_skel : public virtual CORBA::servant_traits<A>::base_type { ... };
// C++
class A_impl: public virtual CORBA::servant_traits<A>::base_type { ... };
Итак, согласно фрагментам, A_impl и A_skel — братья и сестры, происходящие от одного и того же предка.
Решать, что делать, нетривиально, потому что стандарт для первого, C ++ до C ++ 11, mapping [OMG12], имеет 5.40.3 Реализация интерфейса на основе наследования
Классы реализации могут быть получены из сгенерированного базового класса на основе определения интерфейса OMG IDL. Сгенерированные базовые классы известны как каркасные классы, а производные классы известны как классы реализации.
так что это «может», а не «должен» для C ++, до C ++ 11, отображение и фрагменты, приведенные в, соответствуют этому «может»
class POA_A : public virtual PortableServer::ServantBase
{
/* [...] */
}
/* [...] */
class A_impl : public POA_A
{
/* [...] */
};
и это также то, для чего построена устаревшая инфраструктура ORB, с которой я работаю (кроме того, что она предлагает [OMG12] -совместимую реализацию на основе делегирования).
Итак, как связать _skel и _impl в моем маленьком фасаде ORB, совместимом с c ++ 11, чтобы быть [OMG13] -совместимым и ужесточающим impl-кодом против возможного рефакторинга этой части [OMG13]?
Можно, например, рассмотрите возможность получения _impls из класса мультиплексирования наследования в стиле CRTP:
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!
#endifclass IA_impl : public virtual Base<mock::IA> {};int main() {}
но это не совсем соответствует стандартному интерфейсу разработчика.
Рекомендации
[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/CORBA :: servant_traits :: base_type должен преобразовываться в A_skel во время компиляции. Пользователь на самом деле не видит A_skel, это просто деталь реализации. Пользователь определил A_impl, а не только полученный из свойства CORBA :: servant_traits :: base_type.
В 6.26.6, как вы указали, есть ошибка. Классы скелета должны происходить друг от друга, а не от черт, поэтому должно быть так, как показано ниже, также отсутствует C_skel.
// 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 {};
Для чернового проекта V1.1 см. http://osportal.remedy.nl. Мы также можем помочь с вашей задачей, не стесняйтесь связаться со мной напрямую.
Не могли бы вы сообщить об официальной проблеме в OMG для примера в 6.26.2, чтобы мы могли решить ее в версии спецификации V1.2?
В ответ на ответ Джонни Виллемсена:
Хорошо, давайте свяжем кусочки вместе:
Стандартные требования
class A_impl: public virtual CORBA::servant_traits<A>::base_type { ... };
и если это
CORBA :: servant_traits :: base_type должен преобразовываться в A_skel во время компиляции.
будет держаться для A_skel, определенного таким образом
class A_skel : public virtual PortableServer::ServantBase {};
тогда должна быть специализация для template<T>struct CORBA::servant_traits
Итак, я так понимаю, стандарт подразумевает такие зависимости:
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() {}
Я правильно понял?