ADTF
adtf_iid.h
Go to the documentation of this file.
1 
7 #pragma once
8 
9 #include <a_utils/core/result.h>
10 
11 #include <tuple>
12 #include <type_traits>
13 
19 #define ADTF_IID(_interface, _striid) \
20  typedef _interface interface_type; \
21  template<_interface*> \
22  struct interface_info \
23  { \
24  static const char* IID() \
25  { \
26  return _striid; \
27  } \
28  }
29 
44 #ifndef UCOM_RESOLVE
45  #define UCOM_RESOLVE(...) typedef std::tuple < __VA_ARGS__ > hierarchy_type;
46 #endif //UCOM_RESOLVE
47 
48 namespace adtf
49 {
50 namespace ucom
51 {
52 namespace ant
53 {
54 
55 //forward declare for usage in "has_interface_expose_type<>"
56 template<typename...> class interface_expose;
57 
59 namespace detail
60 {
61 
65 template<typename...> struct peel_off_first { typedef void type; };
66 
71 template<typename T, typename... TRemaining>
72 struct peel_off_first<T, TRemaining...>
73 {
74  typedef T type;
75 };//template<typename T, typename...> struct peel_off
76 
81 template<typename T>
82 struct is_template : std::false_type {};
83 
89 template<template<typename...> class C, typename ...T>
90 struct is_template<C<T...>> : std::true_type {};
91 
96 template<typename T>
97 class has_interface_expose_type
98 {
100  struct yes { char x[1]; };
102  struct no { char x[2]; };
103 
109  template<typename C> static yes exists(typename C::interface_expose_type*);
115  template<typename C> static no exists(...);
116 
117 public:
119  static const bool value = sizeof(exists<T>(nullptr)) == sizeof(yes);
120 };//template<typename T> class has_interface_expose_type
121 
126 template<typename T>
127 class has_hierarchy_type
128 {
130  struct yes { char x[1]; };
132  struct no { char x[2]; };
133 
139  template<typename C> static yes exists(typename C::hierarchy_type*);
145  template<typename C> static no exists(...);
146 
147 public:
149  static const bool value = sizeof(exists<T>(nullptr)) == sizeof(yes);
150 };//template<typename T> class has_hierarchy_type
151 
152 
158 template<typename T,
159  typename U = T*>
160 class has_interface_info_type
161 {
163  struct yes { char x[1]; };
165  struct no { char x[2]; };
166 
172  template<typename C>
173  static yes exists(typename C::template interface_info<static_cast<C*>(nullptr)>* = nullptr);
179  template<typename C> static no exists(...);
180 
181 public:
183  static const bool value = sizeof(exists<T>(nullptr)) == sizeof(yes);
184 };//template<typename T> class has_interface_info_type
185 
190 template<typename QueriedInterface, typename ...>
191 class find_intermediate : std::false_type
192 {
193 public:
195  typedef void* first_type;
197  typedef void* second_type;
199  typedef QueriedInterface query_type;
201  typedef typename std::remove_pointer<second_type>::type value_type;
202 };
203 
212 template<typename QueriedInterface, typename ...HierarchyTypes>
213 class find_intermediate<QueriedInterface, std::tuple<HierarchyTypes...>>
214 {
216  template<typename...>
217  struct extract_pair
218  {
219  typedef void key_type;
220  typedef void value_type;
221  typedef void tuple_type;
222  };
223 
230  template<typename KeyType, typename ValueType, typename... TRemaining>
231  struct extract_pair<KeyType, ValueType, TRemaining...>
232  {
233  typedef KeyType key_type;
234  typedef ValueType value_type;
235  typedef std::tuple<TRemaining...> tuple_type;
236  };
237 
239  template<typename...>
240  struct extract_wrapped_pair;
241 
249  template<template<typename, typename> class C,
250  typename KeyType,
251  typename ValueType,
252  typename ...TRemaining>
253  struct extract_wrapped_pair<C<KeyType, ValueType>, TRemaining...> :
254  extract_pair<KeyType, ValueType, TRemaining...> {};
255 
256  //check whether the first type in the tuple is a template or an ordinary type or empty
257  typedef typename peel_off_first<HierarchyTypes...>::type current_type;
258 
259  //check which extract_type pair we need to use (wrapped or unwrapped one)
260  typedef typename
261  std::conditional
262  <
263  is_template<current_type>::value, //check whether wrapped or ordinary key-value-pair
264  extract_wrapped_pair<HierarchyTypes...>,
265  extract_pair<HierarchyTypes...>
266  >::type extract_pair_type;
267 
268  //If we found the QueriedInterface as key type of the current extracted key-value-pair,
269  //we can stop here. Otherwise call this for the remaining parameters in the parameter pack
270  typedef typename
271  std::conditional
272  <
273  std::is_same
274  <
275  typename std::remove_cv<QueriedInterface>::type,
276  typename extract_pair_type::key_type
277  >::value,
278  //using pointers as workaround for problems with typedefing the interfaces later...
279  std::pair<typename extract_pair_type::key_type*,
280  typename extract_pair_type::value_type*>,
281  find_intermediate<QueriedInterface, typename extract_pair_type::tuple_type>
282  >::type pair_type;
283 
284 public:
285  //necessary typedefs for recursive calls
286  typedef typename pair_type::first_type first_type;
287  typedef typename pair_type::second_type second_type;
288 
289  //necessary typedefs for the user
290  typedef typename std::remove_pointer<first_type>::type query_type;
291  typedef typename std::remove_pointer<second_type>::type value_type;
292 
293  //indicate whether the interface is part of any hierarchy
294  static const bool value = !std::is_void<query_type>::value;
295 };//class find_intermediate<QueriedInterface, std::tuple<HierarchyTypes...>>
296 
297 //forward declaration for @ref ucom_resolve()
298 template<typename InterfaceType, bool Cond>
299 struct ucom_resolve_helper;
300 
309 template<typename InterfaceType, typename ObjectType>
310 static typename
311  std::enable_if
312  <
313  find_intermediate< InterfaceType, typename ObjectType::hierarchy_type >::value, //condition
314  typename std::conditional //const correct return type
315  <
316  std::is_const<ObjectType>::value,
317  const InterfaceType*,
318  InterfaceType*
319  >::type
320  >::type
321 ucom_resolve(ObjectType* i_pObject)
322 { //cast to the intermediate type and pass this intermediate type further down
323  typedef typename
324  find_intermediate
325  <
326  InterfaceType,
327  typename ObjectType::hierarchy_type
328  >::value_type intermediate_type;
329 
330  typedef typename
331  std::conditional
332  <
333  std::is_const<ObjectType>::value,
334  const intermediate_type*,
335  intermediate_type*
336  >::type intermediate_pointer;
337 
338  intermediate_pointer pIntermediate = i_pObject;
339  return ucom_resolve_helper<InterfaceType,
340  has_hierarchy_type<intermediate_type>::value>::get(pIntermediate);
341 }
342 
351 template<typename InterfaceType, typename ObjectType>
352 static typename
353  std::enable_if
354  <
355  !find_intermediate< InterfaceType, typename ObjectType::hierarchy_type >::value,//condition
356  typename std::conditional //const correct return type
357  <
358  std::is_const<ObjectType>::value,
359  const InterfaceType*,
360  InterfaceType*
361  >::type
362  >::type
363 ucom_resolve(ObjectType* i_pObject)
364 { //we cannot cast further down, so just return the pointer
365  return i_pObject;
366 }
367 
372 template<typename InterfaceType>
373 struct ucom_resolve_helper<InterfaceType, true>
374 {
382  template<typename IntermediateType>
383  static typename std::conditional
384  <
385  std::is_const<IntermediateType>::value,
386  const InterfaceType*,
387  InterfaceType*
388  >::type
389  get(IntermediateType* i_pObject)
390  {
391  return ucom_resolve<InterfaceType, IntermediateType>(i_pObject);
392  }
393 };
394 
399 template<typename InterfaceType>
400 struct ucom_resolve_helper<InterfaceType, false>
401 {
409  template<typename IntermediateType>
410  static typename std::conditional
411  <
412  std::is_const<IntermediateType>::value,
413  const InterfaceType*,
414  InterfaceType*
415  >::type
416  get(IntermediateType* i_pObject)
417  {
418  return i_pObject;
419  }
420 };
421 
422 }//ns detail
424 
433 template<typename Interface>
434 const char* get_iid()
435 {
436  using namespace std; //remove_const, remove_pointer, is_same
437  typedef typename remove_const<typename remove_pointer<Interface>::type>::type value_type;
438  static_assert(is_same<value_type, typename value_type::interface_type>::value,
439  "get_iid<> failed. Check whether your interface correctly defined ADTF_IID()");
440 
441  constexpr typename value_type::interface_type* pNullInstance = nullptr;
442  (void)(pNullInstance);
443  return value_type::template interface_info<pNullInstance>::IID();
444 }
445 
450 template<typename Interface> const char* get_iid(const Interface&)
451 {
452  return get_iid<Interface>();
453 }
454 
459 template<typename Interface> const char* get_iid(const Interface*)
460 {
461  return get_iid<Interface>();
462 }
463 
470 template<typename ...Interfaces>
472 {
473 private:
475 
479  template<typename ...InterfacesInner>
480  struct iid_dispatch
481  {
490  template<typename Provider, typename VoidType>
491  static tResult dispatch(Provider*, const char*, VoidType*& o_pInterface)
492  {
493  o_pInterface = nullptr;
494  return ERR_NO_INTERFACE;
495  }
496  };//struct iid_dispatch<InterfacesInner...>
497 
503  template<typename Interface, typename ...InterfacesInner>
504  struct iid_dispatch<Interface, InterfacesInner...>
505  {
514  template<typename ObjectType, typename VoidType>
515  static typename std::enable_if<detail::has_hierarchy_type<ObjectType>::value, void>::type
516  resolve(ObjectType* i_pObject, VoidType*& o_pInterface)
517  {
518  o_pInterface = detail::ucom_resolve<Interface>(i_pObject);
519  }
520 
529  template<typename ObjectType, typename VoidType>
530  static typename std::enable_if<!detail::has_hierarchy_type<ObjectType>::value, void>::type
531  resolve(ObjectType* i_pObject, VoidType*& o_pInterface)
532  {
533  typedef typename std::conditional
534  <
535  std::is_const<ObjectType>::value,
536  const Interface*,
537  Interface*
538  >::type interface_pointer;
539  o_pInterface = static_cast<interface_pointer>(i_pObject);
540  }
541 
557  template<typename Provider, typename VoidType>
558  static tResult dispatch(Provider* i_pObj, const char* i_strIID, VoidType*& o_pInterface)
559  { //if Provider is const, we need a const Interface*
560  using namespace std; //std::conditional, std::is_const
561  if (adtf_util::cStringUtil::IsEqual(get_iid<Interface>(), i_strIID))
562  { //check whether we need to resolve things
563  resolve(i_pObj, o_pInterface);
564  }
565  else
566  {
567  return iid_dispatch<InterfacesInner...>::dispatch(i_pObj, i_strIID, o_pInterface);
568  }
569  return ERR_NOERROR;
570  }
571  };//struct iid_dispatch<Interface, InterfacesInner...>
572 
573 public:
575  interface_expose() = delete;
576 
593  template<typename Provider, typename VoidType>
594  static tResult Get(Provider* i_pObj, const char* i_strIID, VoidType*& o_pInterface)
595  { //check whether VoidType is either of type void or const void
596  static_assert(std::is_void<VoidType>::value, "\"VoidType\" must be of type void");
597  return iid_dispatch<Interfaces...>::dispatch(i_pObj, i_strIID, o_pInterface);
598  }
599 };//template<typename ...Interfaces> interface_expose
600 
607 template<typename...>
608 struct inherit_from {};
609 
616 template<typename ...>
618 
623 template<typename...>
625 
642 template<typename Child, typename ...Interfaces, typename ...Parents>
643 class default_object<inherit_from<Parents...>,expose_interfaces<Interfaces...>, Child>
644  : public Parents...
645 {
646 public:
648  typedef interface_expose < Interfaces... > interface_expose_type;
649 
650 protected:
652  virtual ~default_object()
653  {
654  }
655 
671  virtual tResult GetInterface(const char* i_strIID, void*& o_pInterface)
672  { //if there are any UCOM_RESOLVE() information, these are inside the Child type
673  //Use CRTP to perform the cast from this base class to the Child class!
674  static_assert(std::is_base_of<default_object, Child>::value,
675  "The given Child type must be a child type of this default_object type!");
676  return interface_expose_type::Get(static_cast<Child*>(this), i_strIID, o_pInterface);
677  }
678 
694  virtual tResult GetInterface(const char* i_strIID, const void*& o_pInterface) const
695  { //if there are any UCOM_RESOLVE() information, these are inside the Child type
696  //Use CRTP to perform the cast from this base class to the Child class!
697  static_assert(std::is_base_of<default_object, Child>::value,
698  "The given Child type must be a child type of this default_object type!");
699  return interface_expose_type::Get(static_cast<const Child*>(this), i_strIID, o_pInterface);
700  }
701 
705  [[deprecated("Use of Destroy results in a mismatched deallocation. Use adtf::ucom::allocate_object_ptr "
706  "instead.")]] virtual void
707  Destroy() const
708  {
709  delete this;
710  }
711 };//class default_object<inherit_from<Parents...>,expose_interfaces<Interfaces...>>
712 
731 template<typename BASE_OBJECT, typename EXTEND_INTERFACE, typename Child>
732 class extend_object : public BASE_OBJECT, public EXTEND_INTERFACE
733 {
734 public:
735  typedef BASE_OBJECT base_type;
736 
737 protected:
739  virtual ~extend_object() {}
740 
756  virtual tResult GetInterface(const char* i_strIID, void*& o_pInterface)
757  { //cast this to its child class using CRPT to get possible UCOM_RESOLVE() information
758  static_assert(std::is_base_of<extend_object, Child>::value,
759  "The given Child type must be a child type of this extend_object type!");
760  if (IS_FAILED(interface_expose<EXTEND_INTERFACE>::Get(static_cast<Child*>(this),
761  i_strIID,
762  o_pInterface)))
763  {
764  return BASE_OBJECT::GetInterface(i_strIID, o_pInterface);
765  }
767  }
768 
784  virtual tResult GetInterface(const char* i_strIID, const void*& o_pInterface) const
785  { //cast this to its child class using CRPT to get possible UCOM_RESOLVE() information
786  static_assert(std::is_base_of<extend_object, Child>::value,
787  "The given Child type must be a child type of this extend_object type!");
788  if (IS_FAILED(interface_expose<EXTEND_INTERFACE>::Get(static_cast<const Child*>(this),
789  i_strIID,
790  o_pInterface)))
791  {
792  return BASE_OBJECT::GetInterface(i_strIID, o_pInterface);
793  }
795  }
796 
800  [[deprecated("Use of Destroy results in a mismatched deallocation. Use adtf::ucom::allocate_object_ptr "
801  "instead.")]] virtual void
802  Destroy() const
803  {
804  delete this;
805  }
806 };//template<typename BASE_OBJECT, typename EXTEND_INTERFACE> class extend_object
807 
808 //template<typename BASE_OBJECT, typename EXTEND_INTERFACE>
809 //class extend_object<BASE_OBJECT, EXTEND_INTERFACE, void> :
810 // public extend_object
811 // <
812 // BASE_OBJECT,
813 // EXTEND_INTERFACE,
814 // extend_object<BASE_OBJECT, EXTEND_INTERFACE>
815 // >
816 //{};
817 
818 }//ns ant
819 
821 using ant::get_iid;
822 
824 template<typename ...Interfaces>
826 
828 template<typename ...ParentTypes>
829 using inherit_from = ant::inherit_from<ParentTypes...>;
830 
832 template<typename ...InterfaceTypes>
833 using expose_interfaces = ant::expose_interfaces<InterfaceTypes...>;
834 
836 template<typename ...Types>
838 
840 template<typename BASE_CLASS, typename EXTEND_INTERFACE, typename Child>
842 
843 }//ns ucom
844 }//ns adtf
Copyright © Audi Electronics Venture GmbH.
#define RETURN_NOERROR
Return status ERR_NOERROR, which requires the calling function's return type to be tResult.
interface_expose< Interfaces... > interface_expose_type
Enables accessing the exposed interfaces via typedef (e.g. for ucom_cast<> access)
Definition: adtf_iid.h:648
virtual void Destroy() const
Default implementation to destroy an object of this type.
Definition: adtf_iid.h:707
virtual tResult GetInterface(const char *i_strIID, const void *&o_pInterface) const
Default implementation of IObject::GetInterface() provided for const correctness.
Definition: adtf_iid.h:694
virtual tResult GetInterface(const char *i_strIID, void *&o_pInterface)
Default implementation of IObject::GetInterface()
Definition: adtf_iid.h:671
virtual ~default_object()
Protected destructor --> Only the final implementation can be destroyed!
Definition: adtf_iid.h:652
Used to implement IObject::GetInterface() methods with given interfaces to expose.
Definition: adtf_iid.h:733
virtual ~extend_object()
Protected destructor --> Only the final implementation can be destroyed!
Definition: adtf_iid.h:739
virtual void Destroy() const
Default implementation to destroy an object of this type.
Definition: adtf_iid.h:802
virtual tResult GetInterface(const char *i_strIID, const void *&o_pInterface) const
Default implementation of IObject::GetInterface() provided for const correctness.
Definition: adtf_iid.h:784
virtual tResult GetInterface(const char *i_strIID, void *&o_pInterface)
Default implementation of IObject::GetInterface()
Definition: adtf_iid.h:756
BASE_OBJECT base_type
base object type
Definition: adtf_iid.h:735
Meta template struct used to expose all interfaces.
Definition: adtf_iid.h:472
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
bool exists(const Path &path)
Check whether the file or directory exists on the filesystem.
const char * get_iid()
Get the interface id (IID) of the Interface type.
Definition: adtf_iid.h:434
ant::interface_expose< Interfaces... > interface_expose
Alias bringing the latest version of meta struct template ant::interface_expose into scope.
Definition: adtf_iid.h:825
ant::default_object< Types... > default_object
Alias bringing the latest version of meta struct template ant::default_object into scope.
Definition: adtf_iid.h:837
Namespace for entire ADTF SDK.
Declares the class to use when implementing IObject::GetInterface using inheritance.
Definition: adtf_iid.h:624
Meta struct template evaluated at compile time when compiling default_object.
Definition: adtf_iid.h:617
Meta struct template evaluated at compile time when compiling default_object.
Definition: adtf_iid.h:608