ADTF
Loading...
Searching...
No Matches
adtf_iid.h
Go to the documentation of this file.
1
7#pragma once
8
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 constexpr const char* IID() noexcept \
25 { \
26 return _striid; \
27 } \
28 }
29
30
31#ifndef UCOM_RESOLVE
46 #define UCOM_RESOLVE(...) typedef std::tuple<__VA_ARGS__> hierarchy_type;
47#endif // UCOM_RESOLVE
48
49namespace adtf
50{
51namespace ucom
52{
53namespace ant
54{
55
56// forward declare for usage in "has_interface_expose_type<>"
57template<typename...>
59
61namespace detail
62{
63
67template<typename...>
68struct peel_off_first
69{
70 typedef void type;
71};
72
77template<typename T, typename... TRemaining>
78struct peel_off_first<T, TRemaining...>
79{
80 typedef T type;
81}; // template<typename T, typename...> struct peel_off
82
87template<typename T>
88struct is_template : ::std::false_type
89{
90};
91
97template<template<typename...> class C, typename... T>
98struct is_template<C<T...>> : ::std::true_type
99{
100};
101
106template<typename T>
107class has_interface_expose_type
108{
110 struct yes
111 {
112 char x[1];
113 };
115 struct no
116 {
117 char x[2];
118 };
119
125 template<typename C>
126 static yes exists(typename C::interface_expose_type*);
132 template<typename C>
133 static no exists(...);
134
135public:
137 static constexpr bool value = sizeof(exists<T>(nullptr)) == sizeof(yes);
138}; // template<typename T> class has_interface_expose_type
139
144template<typename T>
145class has_hierarchy_type
146{
148 struct yes
149 {
150 char x[1];
151 };
153 struct no
154 {
155 char x[2];
156 };
157
163 template<typename C>
164 static yes exists(typename C::hierarchy_type*);
170 template<typename C>
171 static no exists(...);
172
173public:
175 static constexpr bool value = sizeof(exists<T>(nullptr)) == sizeof(yes);
176}; // template<typename T> class has_hierarchy_type
177
183template<typename T, typename U = T*>
184class has_interface_info_type
185{
187 struct yes
188 {
189 char x[1];
190 };
192 struct no
193 {
194 char x[2];
195 };
196
202 template<typename C>
203 static yes exists(typename C::template interface_info<static_cast<C*>(nullptr)>* = nullptr);
209 template<typename C>
210 static no exists(...);
211
212public:
214 static constexpr bool value = sizeof(exists<T>(nullptr)) == sizeof(yes);
215}; // template<typename T> class has_interface_info_type
216
221template<typename QueriedInterface, typename...>
222class find_intermediate : ::std::false_type
223{
224public:
226 typedef void* first_type;
228 typedef void* second_type;
230 typedef QueriedInterface query_type;
232 typedef typename ::std::remove_pointer_t<second_type> value_type;
233};
234
243template<typename QueriedInterface, typename... HierarchyTypes>
244class find_intermediate<QueriedInterface, ::std::tuple<HierarchyTypes...>>
245{
247 template<typename...>
248 struct extract_pair
249 {
250 typedef void key_type;
251 typedef void value_type;
252 typedef void tuple_type;
253 };
254
261 template<typename KeyType, typename ValueType, typename... TRemaining>
262 struct extract_pair<KeyType, ValueType, TRemaining...>
263 {
264 typedef KeyType key_type;
265 typedef ValueType value_type;
266 typedef ::std::tuple<TRemaining...> tuple_type;
267 };
268
270 template<typename...>
271 struct extract_wrapped_pair;
272
280 template<template<typename, typename> class C, typename KeyType, typename ValueType, typename... TRemaining>
281 struct extract_wrapped_pair<C<KeyType, ValueType>, TRemaining...> : extract_pair<KeyType, ValueType, TRemaining...>
282 {
283 };
284
285 // check whether the first type in the tuple is a template or an ordinary type or empty
286 using current_type = typename peel_off_first<HierarchyTypes...>::type;
287
288 // check which extract_type pair we need to use (wrapped or unwrapped one)
289 using extract_pair_type =
290 typename ::std::conditional_t<is_template<current_type>::value, // check whether wrapped or ordinary
291 // key-value-pair
292 extract_wrapped_pair<HierarchyTypes...>,
293 extract_pair<HierarchyTypes...>>;
294
295 // If we found the QueriedInterface as key type of the current extracted key-value-pair,
296 // we can stop here. Otherwise call this for the remaining parameters in the parameter pack
297 using pair_type = typename ::std::conditional_t<
298 ::std::is_same_v<typename ::std::remove_cv_t<QueriedInterface>, typename extract_pair_type::key_type>,
299 // using pointers as workaround for problems with typedefing the interfaces later...
300 ::std::pair<typename extract_pair_type::key_type*, typename extract_pair_type::value_type*>,
301 find_intermediate<QueriedInterface, typename extract_pair_type::tuple_type>>;
302
303public:
304 // necessary typedefs for recursive calls
305 typedef typename pair_type::first_type first_type;
306 typedef typename pair_type::second_type second_type;
307
308 // necessary typedefs for the user
309 typedef typename ::std::remove_pointer_t<first_type> query_type;
310 typedef typename ::std::remove_pointer_t<second_type> value_type;
311
312 // indicate whether the interface is part of any hierarchy
313 static constexpr bool value = !::std::is_void_v<query_type>;
314}; // class find_intermediate<QueriedInterface, std::tuple<HierarchyTypes...>>
315
316// forward declaration for @ref ucom_resolve()
317template<typename InterfaceType, bool Cond>
318struct ucom_resolve_helper;
319
328template<typename InterfaceType, typename ObjectType>
329static constexpr
330 typename ::std::enable_if_t<
331 find_intermediate<InterfaceType, typename ObjectType::hierarchy_type>::value, // condition
332 typename ::std::conditional_t<::std::is_const_v<ObjectType>, const InterfaceType*, InterfaceType*> // const
333 // correct
334 // return
335 // type
336 >
337 ucom_resolve(ObjectType* i_pObject) noexcept
338{ // cast to the intermediate type and pass this intermediate type further down
339 typedef
340 typename find_intermediate<InterfaceType, typename ObjectType::hierarchy_type>::value_type intermediate_type;
341
342 typedef typename ::std::conditional_t<::std::is_const_v<ObjectType>, const intermediate_type*, intermediate_type*>
343 intermediate_pointer;
344
345 intermediate_pointer pIntermediate = i_pObject;
346 return ucom_resolve_helper<InterfaceType, has_hierarchy_type<intermediate_type>::value>::get(pIntermediate);
347}
348
357template<typename InterfaceType, typename ObjectType>
358static constexpr
359 typename ::std::enable_if_t<
360 !find_intermediate<InterfaceType, typename ObjectType::hierarchy_type>::value, // condition
361 typename ::std::conditional_t<::std::is_const_v<ObjectType>, const InterfaceType*, InterfaceType*> // const
362 // correct
363 // return
364 // type
365 >
366 ucom_resolve(ObjectType* i_pObject) noexcept
367{ // we cannot cast further down, so just return the pointer
368 return i_pObject;
369}
370
375template<typename InterfaceType>
376struct ucom_resolve_helper<InterfaceType, true>
377{
385 template<typename IntermediateType>
386 static constexpr
387 typename ::std::conditional_t<::std::is_const_v<IntermediateType>, const InterfaceType*, InterfaceType*>
388 get(IntermediateType* i_pObject) noexcept
389 {
390 return ucom_resolve<InterfaceType, IntermediateType>(i_pObject);
391 }
392};
393
398template<typename InterfaceType>
399struct ucom_resolve_helper<InterfaceType, false>
400{
408 template<typename IntermediateType>
409 static constexpr
410 typename ::std::conditional_t<::std::is_const_v<IntermediateType>, const InterfaceType*, InterfaceType*>
411 get(IntermediateType* i_pObject) noexcept
412 {
413 return i_pObject;
414 }
415};
416
417} // namespace detail
419
428template<typename Interface>
429constexpr const char* get_iid() noexcept
430{
431 typedef typename ::std::remove_const_t<typename ::std::remove_pointer_t<Interface>> value_type;
432 static_assert(::std::is_same<value_type, typename value_type::interface_type>::value,
433 "get_iid<> failed. Check whether your interface correctly defined ADTF_IID()");
434
435 constexpr typename value_type::interface_type* pNullInstance = nullptr;
436 (void) (pNullInstance);
437 return value_type::template interface_info<pNullInstance>::IID();
438}
439
444template<typename Interface>
445constexpr const char* get_iid(const Interface&) noexcept
446{
447 return get_iid<Interface>();
448}
449
454template<typename Interface>
455constexpr const char* get_iid(const Interface*) noexcept
456{
457 return get_iid<Interface>();
458}
459
466template<typename... Interfaces>
468{
469private:
471
475 template<typename... InterfacesInner>
476 struct iid_dispatch
477 {
486 template<typename Provider, typename VoidType>
487 static constexpr tResult dispatch(Provider*, const char*, VoidType*& o_pInterface) noexcept
488 {
489 o_pInterface = nullptr;
490 return ERR_NO_INTERFACE;
491 }
492 }; // struct iid_dispatch<InterfacesInner...>
493
499 template<typename Interface, typename... InterfacesInner>
500 struct iid_dispatch<Interface, InterfacesInner...>
501 {
510 template<typename ObjectType, typename VoidType>
511 static constexpr typename ::std::enable_if_t<detail::has_hierarchy_type<ObjectType>::value, void>
512 resolve(ObjectType* i_pObject, VoidType*& o_pInterface) noexcept
513 {
514 o_pInterface = detail::ucom_resolve<Interface>(i_pObject);
515 }
516
525 template<typename ObjectType, typename VoidType>
526 static constexpr typename ::std::enable_if_t<!detail::has_hierarchy_type<ObjectType>::value, void>
527 resolve(ObjectType* i_pObject, VoidType*& o_pInterface) noexcept
528 {
529 typedef typename ::std::conditional_t<::std::is_const_v<ObjectType>, const Interface*, Interface*>
530 interface_pointer;
531 o_pInterface = static_cast<interface_pointer>(i_pObject);
532 }
533
549 template<typename Provider, typename VoidType>
550 static tResult dispatch(Provider* i_pObj, const char* i_strIID, VoidType*& o_pInterface) noexcept
551 { // if Provider is const, we need a const Interface*
552 if (adtf_util::cStringUtil::IsEqual(get_iid<Interface>(), i_strIID))
553 { // check whether we need to resolve things
554 resolve(i_pObj, o_pInterface);
555 }
556 else
557 {
558 return iid_dispatch<InterfacesInner...>::dispatch(i_pObj, i_strIID, o_pInterface);
559 }
560 return ERR_NOERROR;
561 }
562 }; // struct iid_dispatch<Interface, InterfacesInner...>
563
564public:
566 interface_expose() = delete;
567
584 template<typename Provider, typename VoidType>
585 static tResult Get(Provider* i_pObj, const char* i_strIID, VoidType*& o_pInterface) noexcept
586 { // check whether VoidType is either of type void or const void
587 static_assert(::std::is_void_v<VoidType>, "\"VoidType\" must be of type void");
588 return iid_dispatch<Interfaces...>::dispatch(i_pObj, i_strIID, o_pInterface);
589 }
590}; // template<typename ...Interfaces> interface_expose
591
598template<typename...>
600{
601};
602
609template<typename...>
611{
612};
613
618template<typename...>
620
637template<typename Child, typename... Interfaces, typename... Parents>
638class default_object<inherit_from<Parents...>, expose_interfaces<Interfaces...>, Child> : public Parents...
639{
640public:
643
644protected:
647 {
648 }
649
665 virtual tResult GetInterface(const char* i_strIID, void*& o_pInterface) noexcept
666 { // if there are any UCOM_RESOLVE() information, these are inside the Child type
667 // Use CRTP to perform the cast from this base class to the Child class!
668 static_assert(::std::is_base_of_v<default_object, Child>,
669 "The given Child type must be a child type of this default_object type!");
670 return interface_expose_type::Get(static_cast<Child*>(this), i_strIID, o_pInterface);
671 }
672
688 virtual tResult GetInterface(const char* i_strIID, const void*& o_pInterface) const noexcept
689 { // if there are any UCOM_RESOLVE() information, these are inside the Child type
690 // Use CRTP to perform the cast from this base class to the Child class!
691 static_assert(::std::is_base_of_v<default_object, Child>,
692 "The given Child type must be a child type of this default_object type!");
693 return interface_expose_type::Get(static_cast<const Child*>(this), i_strIID, o_pInterface);
694 }
695
699 [[deprecated("Use of Destroy results in a mismatched deallocation. Use adtf::ucom::allocate_object_ptr "
700 "instead.")]] virtual void
701 Destroy() const
702 {
703 delete this;
704 }
705}; // class default_object<inherit_from<Parents...>,expose_interfaces<Interfaces...>>
706
725template<typename BASE_OBJECT, typename EXTEND_INTERFACE, typename Child>
726class extend_object : public BASE_OBJECT, public EXTEND_INTERFACE
727{
728public:
729 typedef BASE_OBJECT base_type;
730
731protected:
734 {
735 }
736
752 virtual tResult GetInterface(const char* i_strIID, void*& o_pInterface) noexcept
753 { // cast this to its child class using CRPT to get possible UCOM_RESOLVE() information
754 static_assert(::std::is_base_of_v<extend_object, Child>,
755 "The given Child type must be a child type of this extend_object type!");
756 if (IS_FAILED(interface_expose<EXTEND_INTERFACE>::Get(static_cast<Child*>(this), i_strIID, o_pInterface)))
757 {
758 return BASE_OBJECT::GetInterface(i_strIID, o_pInterface);
759 }
761 }
762
778 virtual tResult GetInterface(const char* i_strIID, const void*& o_pInterface) const noexcept
779 { // cast this to its child class using CRPT to get possible UCOM_RESOLVE() information
780 static_assert(::std::is_base_of_v<extend_object, Child>,
781 "The given Child type must be a child type of this extend_object type!");
782 if (IS_FAILED(interface_expose<EXTEND_INTERFACE>::Get(static_cast<const Child*>(this), i_strIID, o_pInterface)))
783 {
784 return BASE_OBJECT::GetInterface(i_strIID, o_pInterface);
785 }
787 }
788
792 [[deprecated("Use of Destroy results in a mismatched deallocation. Use adtf::ucom::allocate_object_ptr "
793 "instead.")]] virtual void
794 Destroy() const
795 {
796 delete this;
797 }
798}; // template<typename BASE_OBJECT, typename EXTEND_INTERFACE> class extend_object
799
800// template<typename BASE_OBJECT, typename EXTEND_INTERFACE>
801// class extend_object<BASE_OBJECT, EXTEND_INTERFACE, void> :
802// public extend_object
803// <
804// BASE_OBJECT,
805// EXTEND_INTERFACE,
806// extend_object<BASE_OBJECT, EXTEND_INTERFACE>
807// >
808//{};
809
810} // namespace ant
811
813using ant::get_iid;
814
816template<typename... Interfaces>
818
820template<typename... ParentTypes>
821using inherit_from = ant::inherit_from<ParentTypes...>;
822
824template<typename... InterfaceTypes>
825using expose_interfaces = ant::expose_interfaces<InterfaceTypes...>;
826
828template<typename... Types>
830
832template<typename BASE_CLASS, typename EXTEND_INTERFACE, typename Child>
834
835} // namespace ucom
836} // namespace adtf
#define IS_FAILED(s)
Check if result is failed.
Definition result.h:20
A_UTILS_NS::cResult tResult
For backwards compatibility and to bring latest version into scope.
Definition result.h:736
#define RETURN_NOERROR
Return status ERR_NOERROR, which requires the calling function's return type to be tResult.
Definition result.h:29
virtual ~default_object()
Protected destructor --> Only the final implementation can be destroyed!
Definition adtf_iid.h:646
virtual tResult GetInterface(const char *i_strIID, void *&o_pInterface) noexcept
Default implementation of IObject::GetInterface()
Definition adtf_iid.h:665
virtual void Destroy() const
Default implementation to destroy an object of this type.
Definition adtf_iid.h:701
interface_expose< Interfaces... > interface_expose_type
Enables accessing the exposed interfaces via typedef (e.g. for ucom_cast<> access)
Definition adtf_iid.h:642
virtual tResult GetInterface(const char *i_strIID, const void *&o_pInterface) const noexcept
Default implementation of IObject::GetInterface() provided for const correctness.
Definition adtf_iid.h:688
Used to implement IObject::GetInterface() methods with given interfaces to expose.
Definition adtf_iid.h:727
virtual tResult GetInterface(const char *i_strIID, const void *&o_pInterface) const noexcept
Default implementation of IObject::GetInterface() provided for const correctness.
Definition adtf_iid.h:778
virtual tResult GetInterface(const char *i_strIID, void *&o_pInterface) noexcept
Default implementation of IObject::GetInterface()
Definition adtf_iid.h:752
BASE_OBJECT base_type
base object type
Definition adtf_iid.h:729
virtual void Destroy() const
Default implementation to destroy an object of this type.
Definition adtf_iid.h:794
virtual ~extend_object()
Protected destructor --> Only the final implementation can be destroyed!
Definition adtf_iid.h:733
Definition adtf_iid.h:468
constexpr const char * get_iid() noexcept
Definition adtf_iid.h:429
ant::default_object< Types... > default_object
Alias bringing the latest version of meta struct template ant::default_object into scope.
Definition adtf_iid.h:829
ant::extend_object< BASE_CLASS, EXTEND_INTERFACE, Child > extend_object
Alias bringing the latest version of meta struct template ant::extend_object into scope.
Definition adtf_iid.h:833
ant::inherit_from< ParentTypes... > inherit_from
Alias bringing the latest version of meta struct template ant::inherit_from into scope.
Definition adtf_iid.h:821
ant::interface_expose< Interfaces... > interface_expose
Alias bringing the latest version of meta struct template ant::interface_expose into scope.
Definition adtf_iid.h:817
ant::expose_interfaces< InterfaceTypes... > expose_interfaces
Alias bringing the latest version of meta struct template ant::expose_interfaces into scope.
Definition adtf_iid.h:825
Namespace for all functionality provided by ADTF and its SDKs.
Definition adtf_client_connector.h:14
Declares the class to use when implementing IObject::GetInterface() using inheritance.
Definition adtf_iid.h:619
Meta struct template evaluated at compile time when compiling default_object.
Definition adtf_iid.h:611
Meta struct template evaluated at compile time when compiling default_object.
Definition adtf_iid.h:600