ADTF
object.h
Go to the documentation of this file.
1 
7 #pragma once
8 
9 namespace adtf
10 {
11 namespace ucom
12 {
13 namespace catwo
14 {
15 namespace detail
16 {
17 
19 template<typename T>
20 class has_interface_type : private T
21 {
22  typedef char one;
23  typedef long two;
24 
25  template<typename C> static one test(typename C::interface_type*);
26  template<typename C> static two test(...);
27 
28 public:
29  enum { value = sizeof(test<T>(nullptr)) == sizeof(char) };
30 };
31 
32 template <typename T>
33 using is_interface_helper = std::is_same<T, typename T::interface_type>; // see get_iid
34 
36 template<typename T, typename Enable = void>
37 struct is_interface;
38 
39 template<typename T>
40 struct is_interface<T, typename std::enable_if<!has_interface_type<T>::value>::type> : std::false_type
41 {
42 };
43 
44 template<typename T>
45 struct is_interface<T, typename std::enable_if<has_interface_type<T>::value && !is_interface_helper<T>::value>::type> : std::false_type
46 {
47 };
48 
49 template<typename T>
50 struct is_interface<T, typename std::enable_if<has_interface_type<T>::value && is_interface_helper<T>::value>::type> : std::true_type
51 {
52 };
53 
55 template <typename T>
56 class has_get_interface: private T
57 {
58  typedef char one;
59  typedef long two;
60 
61  template <typename C> static one test(decltype(static_cast<tResult(T::*)(const char*, void*&)>(&has_get_interface<C>::GetInterface)));
62  template <typename C> static two test(...);
63 
64 public:
65  enum { value = sizeof(test<T>(static_cast<tResult(T::*)(const char*, void*&)>(nullptr))) == sizeof(char) };
66 };
67 
68 // template that dispatches type resolution to static error, dynamic GetInterface or inline type comparison
69 template<typename BaseClass, typename Enable = void>
71 
72 template<>
73 struct base_dispatcher<void, void>
74 {
75 protected:
76  virtual ~base_dispatcher() = default;
77 
78  inline tResult GetInterfaceStatic(const char* /* i_strIID */, void*& /* o_pInterface */)
79  {
80  RETURN_ERROR(ERR_NO_INTERFACE);
81  }
82 
83  inline tResult GetInterfaceStatic(const char* /* i_strIID */, const void*& /* o_pInterface */) const
84  {
85  RETURN_ERROR(ERR_NO_INTERFACE);
86  }
87 
88 public:
89  enum { dispatch = false };
90 };
91 
92 
94 template<typename BaseClass>
95 struct base_dispatcher<BaseClass, typename std::enable_if<!is_interface<BaseClass>::value && !has_get_interface<BaseClass>::value>::type> :
96  public BaseClass
97 {
98  protected:
99  using BaseClass::BaseClass;
100 
101  virtual ~base_dispatcher() = default;
102 
103  inline tResult GetInterfaceStatic(const char* /* i_strIID */, void*& /* o_pInterface */)
104  {
105  RETURN_ERROR(ERR_NO_INTERFACE);
106  }
107 
108  inline tResult GetInterfaceStatic(const char* /* i_strIID */, const void*& /* o_pInterface */) const
109  {
110  RETURN_ERROR(ERR_NO_INTERFACE);
111  }
112 };
113 
114 
116 template <typename BaseClass>
117 struct base_dispatcher<BaseClass, typename std::enable_if<!is_interface<BaseClass>::value && has_get_interface<BaseClass>::value>::type> :
118  public BaseClass
119 {
120  protected:
121  using BaseClass::BaseClass;
122 
123  virtual ~base_dispatcher() = default;
124 
125  inline tResult GetInterfaceStatic(const char* i_strIID, void*& o_pInterface)
126  {
127  return BaseClass::GetInterface(i_strIID, o_pInterface);
128  }
129 
130  inline tResult GetInterfaceStatic(const char* i_strIID, const void*& o_pInterface) const
131  {
132  return BaseClass::GetInterface(i_strIID, o_pInterface);
133  }
134 };
135 
137 template <typename Interface>
138 struct base_dispatcher<Interface, typename std::enable_if<is_interface<Interface>::value>::type>:
139  Interface
140 {
141  protected:
142  using Interface::Interface;
143 
144  virtual ~base_dispatcher() = default;
145 
146  inline tResult GetInterfaceStatic(const char* i_strIID, void*& o_pInterface)
147  {
148  if (util::cStringUtil::IsEqual(ucom::get_iid<Interface>(), i_strIID))
149  {
150  o_pInterface = static_cast<Interface*>(this);
152  }
153 
154  RETURN_ERROR(ERR_NO_INTERFACE);
155  }
156 
157  inline tResult GetInterfaceStatic(const char* i_strIID, const void*& o_pInterface) const
158  {
159  if (util::cStringUtil::IsEqual(ucom::get_iid<Interface>(), i_strIID))
160  {
161  o_pInterface = static_cast<const Interface*>(this);
163  }
164 
165  RETURN_ERROR(ERR_NO_INTERFACE);
166  }
167 };
168 
171 template <typename Base, typename NextBase>
173  public base_dispatcher<Base>,
174  public base_dispatcher<NextBase>
175 {
176  protected:
178 
179  tResult GetInterface(const char* i_strIID, void*& o_pInterface)
180  {
181  if (IS_OK(base_dispatcher<Base>::GetInterfaceStatic(i_strIID, o_pInterface)))
182  {
184  }
185 
186  return base_dispatcher<NextBase>::GetInterfaceStatic(i_strIID, o_pInterface);
187  }
188 
189  tResult GetInterface(const char* i_strIID, const void*& o_pInterface) const
190  {
191  if (IS_OK(base_dispatcher<Base>::GetInterfaceStatic(i_strIID, o_pInterface)))
192  {
194  }
195 
196  return base_dispatcher<NextBase>::GetInterfaceStatic(i_strIID, o_pInterface);
197  }
198 
199  // Base interface is deprecated, but still needs to be overloaded to be able to correctly call the destructor.
200 #if defined(__GNUC__)
201  #pragma GCC diagnostic push
202  #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
203 #endif
205  void Destroy() const
206  {
207  delete this;
208  }
209 #if defined(__GNUC__)
210  #pragma GCC diagnostic pop
211 #endif
212 };
213 
216 template <typename Base, typename NextBase>
218  public derive_from_without_hierarchy<Base, NextBase>
219 {
220  public:
222 
223  protected:
225 };
226 
227 template<typename Base, typename ...Interfaces>
229 {
230  protected:
232 
233  tResult GetInterface(const char* i_strIID, void*& o_pInterface)
234  {
235  if (IS_OK(detail::base_dispatcher<Base>::GetInterfaceStatic(i_strIID, o_pInterface)))
236  {
238  }
239  return ucom::ant::interface_expose<Interfaces...>::Get(this, i_strIID, o_pInterface);
240  }
241 
242  tResult GetInterface(const char* i_strIID, const void*& o_pInterface) const
243  {
244  if (IS_OK(detail::base_dispatcher<Base>::GetInterfaceStatic(i_strIID, o_pInterface)))
245  {
247  }
248  return ucom::ant::interface_expose<Interfaces...>::Get(this, i_strIID, o_pInterface);
249  }
250 
251  // Base interface is deprecated, but still needs to be overloaded to be able to correctly call the destructor.
252 #if defined(__GNUC__)
253  #pragma GCC diagnostic push
254  #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
255 #endif
257  void Destroy() const
258  {
259  delete this;
260  }
261 #if defined(__GNUC__)
262  #pragma GCC diagnostic pop
263 #endif
264 };
265 
267 template <typename ...Bases>
269 {
270 };
271 
273 template <typename Base, typename NextBase>
274 using derive_from_type = typename std::conditional<std::is_same<NextBase, object_without_iobject<>>::value,
276  typename std::conditional<std::is_base_of<Base, NextBase>::value,
278  typename std::conditional<std::is_base_of<ucom::ant::IObject, Base>::value,
281 
285 template <typename Base, typename NextBase>
286 class derive_from: public derive_from_type<Base, NextBase>
287 {
288  public:
290 };
291 
293 template <typename ...Bases>
294 struct parent_follows_child: std::false_type
295 {
296 };
297 
299 template <typename Base, typename NextBase, typename ...Bases>
300 struct parent_follows_child<Base, NextBase, Bases...>:
301  std::conditional<!std::is_same<NextBase, Base>::value &&
302  std::is_base_of<NextBase, Base>::value,
303  std::true_type,
304  parent_follows_child<Base, Bases...>>::type
305 {
306 };
307 
309 template <typename Base, typename ...Bases>
310 class object_without_iobject<Base, Bases...>:
311  public derive_from<Base, object_without_iobject<Bases...>>
312 {
313  public:
315  {
317  "One or more of the template parameters are in the wrong order. "
318  "Make sure that derived classes are specified after their parents.");
319  }
320 
321  protected:
322  using derive_from<Base, object_without_iobject<Bases...>>::derive_from;
323 };
324 
325 }//detail
326 
394 template <typename ...Bases>
395 class object:
396  public ucom::ant::IObject
397 {
398  public:
399  virtual ~object() = default;
400 
401  tResult GetInterface(const char* i_strIID, void*& o_pInterface) override
402  {
403  return ucom::ant::interface_expose<ucom::ant::IObject>::Get(this, i_strIID, o_pInterface);
404  }
405 
406  tResult GetInterface(const char* i_strIID, const void*& o_pInterface) const override
407  {
408  return ucom::ant::interface_expose<ucom::ant::IObject>::Get(this, i_strIID, o_pInterface);
409  }
410 
411  // Base interface is deprecated, but still needs to be overloaded to be able to correctly call the destructor.
412 #if defined(__GNUC__)
413  #pragma GCC diagnostic push
414  #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
415 #endif
417  void Destroy() const override
418  {
419  delete this;
420  }
421 #if defined(__GNUC__)
422  #pragma GCC diagnostic pop
423 #endif
424 };
425 
426 // Workaround for MSVC bug where writing this template inline twice would not be recognized as being the same base class
427 template<typename Base, typename... Bases>
428 using object_base_type_helper =
429  typename std::conditional<std::is_base_of<object<>, Base>::value,
430  detail::derive_from<Base, detail::object_without_iobject<Bases...>>,
431  detail::derive_from<Base, object<Bases...>>>::type;
432 
434 template<typename Base, typename... Bases>
435 class object<Base, Bases...> : public object_base_type_helper<Base, Bases...>
436 {
437 public:
438  using object_base_type_helper<Base, Bases...>::object_base_type_helper;
439 
440  object()
441  {
443  "One or more of the template parameters are in the wrong order. "
444  "Make sure that derived classes are specified after their parents.");
445  }
446 };
447 
448 }//namespace catwo
449 
450 using catwo::object;
451 
452 }//namespace ucom
453 }//namespace adtf
#define UCOM_RESOLVE(...)
Resolve a path to a base class which is inherited multiple times.
Definition: adtf_iid.h:45
#define RETURN_NOERROR
Return status ERR_NOERROR, which requires the calling function's return type to be tResult.
#define RETURN_ERROR(code)
Return specific error code, which requires the calling function's return type to be tResult.
Base class for every interface type within the uCOM.
Definition: object_intf.h:33
static tResult Get(Provider *i_pObj, const char *i_strIID, VoidType *&o_pInterface)
Get the interface with IID i_strIID exposed from i_pObj.
Definition: adtf_iid.h:594
This template checks if the first base implements the requested interface, otherwise checks the next ...
Definition: object.h:219
This template checks if the first base implements the requested interface, otherwise checks the next ...
Definition: object.h:175
void Destroy() const
Possibly required override of IObject::Destroy() while destructor is still non-virtual.
Definition: object.h:205
This template checks if the first base implements the requested interface, otherwise checks the next ...
Definition: object.h:287
void Destroy() const
Possibly required override of IObject::Destroy() while destructor is still non-virtual.
Definition: object.h:257
template that checks whether a type has an accessible (protected or public) GetInterface method.
Definition: object.h:57
template that checks whether a type has an accessible interface_type property.
Definition: object.h:21
This template is used to prevent an ambiguous base of ucom::ant::IObject.
Definition: object.h:269
Use this template if you want to implement an ucom::ant::IObject based Interface and/or subclass an e...
Definition: object.h:397
void Destroy() const override
Switch from non-virtual destructor to virtual destructor.
Definition: object.h:417
tResult GetInterface(const char *i_strIID, const void *&o_pInterface) const override
Provides const correct interface querying.
Definition: object.h:406
tResult GetInterface(const char *i_strIID, void *&o_pInterface) override
Query interfaces on an object.
Definition: object.h:401
typename std::conditional< std::is_same< NextBase, object_without_iobject<> >::value, expose_additional_interfaces< Base >, typename std::conditional< std::is_base_of< Base, NextBase >::value, expose_additional_interfaces< NextBase, Base >, typename std::conditional< std::is_base_of< ucom::ant::IObject, Base >::value, derive_from_with_hierarchy< Base, NextBase >, derive_from_without_hierarchy< Base, NextBase > >::type >::type >::type derive_from_type
this intermediate type is used to keep binary compatibility
Definition: object.h:280
Namespace for entire ADTF SDK.
template that checks whether a type is an interface with an IID.
Definition: object.h:37
this template checks if parent interfaces are not specified before their children
Definition: object.h:295