/* * Copyright (c) 2024 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef META_BASE_INTERFACE_TRAITS_H #define META_BASE_INTERFACE_TRAITS_H #include #include #include #include BASE_BEGIN_NAMESPACE() namespace Internals { class ptr_base; } template class shared_ptr; template class weak_ptr; BASE_END_NAMESPACE() META_BEGIN_NAMESPACE() template class HasGetInterfaceMethod final { template static BASE_NS::true_type TestSignature(CORE_NS::IInterface* (T::*)(const BASE_NS::Uid&)); template static decltype(TestSignature((CORE_NS::IInterface * (T::*)(const BASE_NS::Uid&)) & T::GetInterface)) Test( std::nullptr_t); template static BASE_NS::false_type Test(...); public: static constexpr bool value = decltype(Test(nullptr))::value; // NOLINT(readability-identifier-naming) }; // NOLINTBEGIN(readability-identifier-naming) /** * @brief Check if type has GetInterface member functions (see IInterface). */ template inline constexpr bool HasGetInterfaceMethod_v = HasGetInterfaceMethod::value; /** * @brief Check if type is an interface, i.e. implements reference counting and GetInterface member functions. */ template inline constexpr bool IsKindOfInterface_v = BASE_NS::is_convertible_v*, CORE_NS::IInterface*>; // NOLINTEND(readability-identifier-naming) // type trait for checking if the type has equality comparison template struct HasEqualOperator { template static auto Test(U*) -> decltype(BASE_NS::declval() == BASE_NS::declval()); template static auto Test(...) -> BASE_NS::false_type; using type = typename BASE_NS::is_same(nullptr))>::type; }; /** * @brief Check if the type can be compared with equality operators. */ template inline constexpr bool HasEqualOperator_v = HasEqualOperator::type::value; // NOLINT(readability-identifier-naming) template struct HasInEqualOperator { template static auto Test(U*) -> decltype(BASE_NS::declval() != BASE_NS::declval()); template static auto Test(...) -> BASE_NS::false_type; using type = typename BASE_NS::is_same(nullptr))>::type; }; // NOLINTBEGIN(readability-identifier-naming) /** * @brief Check if the type can be compared with in-equality operators. */ template inline constexpr bool HasInEqualOperator_v = HasInEqualOperator::type::value; // NOLINTEND(readability-identifier-naming) // NOLINTBEGIN(readability-identifier-naming) /** * @brief Check if the type is "kind of" smart pointer, i.e. derived from BASE_NS::ptr_base. */ template constexpr bool IsKindOfPointer_v = BASE_NS::is_convertible_v, BASE_NS::Internals::ptr_base&>; // NOLINTEND(readability-identifier-naming) // NOLINTBEGIN(readability-identifier-naming) /** * @brief Check if the type is a pointer which is convertible to IInterface pointer. */ template constexpr bool IsKindOfIInterface_v = BASE_NS::is_convertible_v, CORE_NS::IInterface*>; // NOLINTEND(readability-identifier-naming) /** * @brief SFINAE construct for checking if entity can be used as property bind function. */ template using EnableIfProperBindFunction = decltype(BASE_NS::declval()(BASE_NS::declval()())); template T CallTestFunc(const T&); template using EnableIfBindFunction = decltype(CallTestFunc(BASE_NS::declval()())); template struct CanInvokeWithArgumentsImpl { constexpr static bool value = false; // NOLINT(readability-identifier-naming) }; template struct CanInvokeWithArgumentsImpl()(BASE_NS::declval()...), void())> { constexpr static bool value = true; // NOLINT(readability-identifier-naming) }; // NOLINTBEGIN(readability-identifier-naming) /** * @brief Check if callable entity is compatible with given function signature. */ template constexpr bool CanInvokeWithArguments_v = CanInvokeWithArgumentsImpl::value; // NOLINTEND(readability-identifier-naming) template using EnableIfCanInvokeWithArguments = typename BASE_NS::enable_if_t>; template using ToggleConst = BASE_NS::conditional_t, BASE_NS::remove_const_t, const Type>; template struct ToggleConstSharedPtrImpl; template struct ToggleConstSharedPtrImpl> { using type = BASE_NS::shared_ptr; }; template struct ToggleConstSharedPtrImpl> { using type = BASE_NS::shared_ptr; }; template using ToggleConstSharedPtr = typename ToggleConstSharedPtrImpl::type; /* We want to check if one can cast shared_ptr to PropPtr. This requires in our case baseclass relation. * (1) BaseProp and PropPtr are both const or non-const - This case is easy, just check directly the conversion. * (2) BaseProp is const and PropPtr is non-const - This is not allowed case since we don't cast away constness * (3) BaseProp is non-const and PropPtr is const - This case is just adding a const Since PropPtr is the derived class, we need to see if we can convert that to the base class: is_convertible> works for (1) and (2) but not for (3) We want it to work for (1) and (3) but not (2), so we can achieve this by swapping the constness of the types. */ // NOLINTBEGIN(readability-identifier-naming) template inline constexpr bool IsCompatibleBaseProperty_v = BASE_NS::is_convertible_v, BASE_NS::shared_ptr>>; // NOLINTEND(readability-identifier-naming) template using EnableIfCompatibleBaseProperty = BASE_NS::enable_if_t>; /** * @brief Check if type is shared_ptr */ template struct IsSharedPtr { static constexpr bool value = false; // NOLINT(readability-identifier-naming) }; template struct IsSharedPtr> { static constexpr bool value = true; // NOLINT(readability-identifier-naming) template using rebind = BASE_NS::shared_ptr; }; template struct IsWeakPtr { static constexpr bool value = false; // NOLINT(readability-identifier-naming) }; template struct IsWeakPtr> { static constexpr bool value = true; // NOLINT(readability-identifier-naming) template using rebind = BASE_NS::weak_ptr; }; template constexpr bool IsWeakPtr_v = IsWeakPtr::value; // NOLINT(readability-identifier-naming) /** * @brief Check if type is shared_ptr or weak_ptr */ template struct IsSharedOrWeakPtr { static constexpr bool value = false; // NOLINT(readability-identifier-naming) }; template struct IsSharedOrWeakPtr> { static constexpr bool value = true; // NOLINT(readability-identifier-naming) template using rebind = BASE_NS::shared_ptr; static constexpr bool is_const = BASE_NS::is_const_v; // NOLINT(readability-identifier-naming) }; template struct IsSharedOrWeakPtr> { static constexpr bool value = true; // NOLINT(readability-identifier-naming) template using rebind = BASE_NS::weak_ptr; static constexpr bool is_const = BASE_NS::is_const_v; // NOLINT(readability-identifier-naming) }; template constexpr bool IsConstPtr_v = IsSharedOrWeakPtr::is_const; // NOLINT(readability-identifier-naming) /** * @brief Check if type is shared_ptr or weak_ptr */ template constexpr bool IsSharedOrWeakPtr_v = IsSharedOrWeakPtr::value; // NOLINT(readability-identifier-naming) template using InterfaceCheck = META_NS::BoolWrap*>>; // NOLINTBEGIN(readability-identifier-naming) template constexpr bool IsInterfacePtr_v = IsSharedOrWeakPtr_v && META_NS::IsDetectedWithValue_v; // NOLINTEND(readability-identifier-naming) // NOLINTBEGIN(readability-identifier-naming) template constexpr bool IsInterfaceWeakPtr_v = IsInterfacePtr_v && IsWeakPtr::value; // NOLINTEND(readability-identifier-naming) template struct FuncToSignature; template struct FuncToSignature { using type = Ret(Args...); constexpr static bool IS_CONST = false; }; template struct FuncToSignature { using type = Ret(Args...); constexpr static bool IS_CONST = true; }; template struct FuncToSignature { using type = Ret(Args...); constexpr static bool IS_CONST = false; }; template struct FuncToSignature { using type = Ret(Args...); constexpr static bool IS_CONST = true; }; template struct FuncToSignature : FuncToSignature {}; /** * @brief Convert member function types, function types and callable entity types to function signature. * Note: Does not work with multiple overloads of operator(). */ template using FuncToSignature_t = typename FuncToSignature::type; META_END_NAMESPACE() #endif