/*
* 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