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  void Destroy() const
200  {
201  delete this;
202  }
203 };
204 
207 template <typename Base, typename NextBase>
209  public derive_from_without_hierarchy<Base, NextBase>
210 {
211  public:
213 
214  protected:
216 };
217 
218 template<typename Base, typename ...Interfaces>
220 {
221  protected:
223 
224  tResult GetInterface(const char* i_strIID, void*& o_pInterface)
225  {
226  if (IS_OK(detail::base_dispatcher<Base>::GetInterfaceStatic(i_strIID, o_pInterface)))
227  {
229  }
230  return ucom::ant::interface_expose<Interfaces...>::Get(this, i_strIID, o_pInterface);
231  }
232 
233  tResult GetInterface(const char* i_strIID, const void*& o_pInterface) const
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  void Destroy() const
243  {
244  delete this;
245  }
246 };
247 
249 template <typename ...Bases>
251 {
252 };
253 
255 template <typename Base, typename NextBase>
256 using derive_from_type = typename std::conditional<std::is_same<NextBase, object_without_iobject<>>::value,
258  typename std::conditional<std::is_base_of<Base, NextBase>::value,
260  typename std::conditional<std::is_base_of<ucom::ant::IObject, Base>::value,
263 
267 template <typename Base, typename NextBase>
268 class derive_from: public derive_from_type<Base, NextBase>
269 {
270  public:
272 };
273 
275 template <typename ...Bases>
276 struct parent_follows_child: std::false_type
277 {
278 };
279 
281 template <typename Base, typename NextBase, typename ...Bases>
282 struct parent_follows_child<Base, NextBase, Bases...>:
283  std::conditional<!std::is_same<NextBase, Base>::value &&
284  std::is_base_of<NextBase, Base>::value,
285  std::true_type,
286  parent_follows_child<Base, Bases...>>::type
287 {
288 };
289 
291 template <typename Base, typename ...Bases>
292 class object_without_iobject<Base, Bases...>:
293  public derive_from<Base, object_without_iobject<Bases...>>
294 {
295  public:
297  {
299  "One or more of the template parameters are in the wrong order. "
300  "Make sure that derived classes are specified after their parents.");
301  }
302 
303  protected:
304  using derive_from<Base, object_without_iobject<Bases...>>::derive_from;
305 };
306 
307 }//detail
308 
376 template <typename ...Bases>
377 class object:
378  public ucom::ant::IObject
379 {
380  protected:
381  virtual ~object() = default;
382 
383  public:
384  tResult GetInterface(const char* i_strIID, void*& o_pInterface) override
385  {
386  return ucom::ant::interface_expose<ucom::ant::IObject>::Get(this, i_strIID, o_pInterface);
387  }
388 
389  tResult GetInterface(const char* i_strIID, const void*& o_pInterface) const override
390  {
391  return ucom::ant::interface_expose<ucom::ant::IObject>::Get(this, i_strIID, o_pInterface);
392  }
393 
394  void Destroy() const override
395  {
396  delete this;
397  }
398 };
399 
400 // Workaround for MSVC bug where writing this template inline twice would not be recognized as being the same base class
401 template<typename Base, typename... Bases>
402 using object_base_type_helper =
403  typename std::conditional<std::is_base_of<object<>, Base>::value,
404  detail::derive_from<Base, detail::object_without_iobject<Bases...>>,
405  detail::derive_from<Base, object<Bases...>>>::type;
406 
408 template<typename Base, typename... Bases>
409 class object<Base, Bases...> : public object_base_type_helper<Base, Bases...>
410 {
411 public:
412  using object_base_type_helper<Base, Bases...>::object_base_type_helper;
413 
414  object()
415  {
417  "One or more of the template parameters are in the wrong order. "
418  "Make sure that derived classes are specified after their parents.");
419  }
420 };
421 
422 }//namespace catwo
423 
424 using catwo::object;
425 
426 }//namespace ucom
427 }//namespace adtf
#define UCOM_RESOLVE(...)
Resolve a path to a base class which is inherited multiple times.
Definition: adtf_iid.h:40
#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:31
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:589
This template checks if the first base implements the requested interface, otherwise checks the next ...
Definition: object.h:210
This template checks if the first base implements the requested interface, otherwise checks the next ...
Definition: object.h:175
This template checks if the first base implements the requested interface, otherwise checks the next ...
Definition: object.h:269
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:251
Use this template if you want to implement an ucom::ant::IObject based Interface and/or subclass an e...
Definition: object.h:379
void Destroy() const override
Destruct and deallocate instantiations of type IObject.
Definition: object.h:394
tResult GetInterface(const char *i_strIID, const void *&o_pInterface) const override
Provides const correct interface querying.
Definition: object.h:389
tResult GetInterface(const char *i_strIID, void *&o_pInterface) override
Query interfaces on an object.
Definition: object.h:384
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:262
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:277