#ifndef BASE_FUNCTIONAL_UNRETAINED_TRAITS_H_
#define BASE_FUNCTIONAL_UNRETAINED_TRAITS_H_
#include <type_traits>
#include "base/types/is_complete.h"
#include "base/types/same_as_any.h"
#include "build/build_config.h"
#define BASE_INTERNAL_LIST_OF_SAFE_FOR_UNRETAINED \
BASE_INTERNAL_SAFE_FOR_UNRETAINED(ANativeWindow) \
BASE_INTERNAL_SAFE_FOR_UNRETAINED(DBusMessage) \
BASE_INTERNAL_SAFE_FOR_UNRETAINED(HWND__) \
BASE_INTERNAL_SAFE_FOR_UNRETAINED(VkBuffer_T) \
BASE_INTERNAL_SAFE_FOR_UNRETAINED(VkDeviceMemory_T) \
BASE_INTERNAL_SAFE_FOR_UNRETAINED(VkImage_T) \
BASE_INTERNAL_SAFE_FOR_UNRETAINED(VkSemaphore_T) \
BASE_INTERNAL_SAFE_FOR_UNRETAINED(VmaAllocation_T) \
BASE_INTERNAL_SAFE_FOR_UNRETAINED(WGPUAdapterImpl) \
BASE_INTERNAL_SAFE_FOR_UNRETAINED(fpdf_action_t__) \
BASE_INTERNAL_SAFE_FOR_UNRETAINED(fpdf_annotation_t__) \
BASE_INTERNAL_SAFE_FOR_UNRETAINED(fpdf_attachment_t__) \
BASE_INTERNAL_SAFE_FOR_UNRETAINED(fpdf_bookmark_t__) \
BASE_INTERNAL_SAFE_FOR_UNRETAINED(fpdf_document_t__) \
BASE_INTERNAL_SAFE_FOR_UNRETAINED(fpdf_form_handle_t__) \
BASE_INTERNAL_SAFE_FOR_UNRETAINED(fpdf_page_t__) \
BASE_INTERNAL_SAFE_FOR_UNRETAINED(fpdf_structelement_t__) \
BASE_INTERNAL_SAFE_FOR_UNRETAINED(fpdf_structelement_attr_t__) \
BASE_INTERNAL_SAFE_FOR_UNRETAINED(fpdf_structelement_attr_value_t__) \
BASE_INTERNAL_SAFE_FOR_UNRETAINED(hb_set_t) \
BASE_INTERNAL_SAFE_FOR_UNRETAINED(wl_gpu) \
BASE_INTERNAL_SAFE_FOR_UNRETAINED(wl_shm) \
BASE_INTERNAL_SAFE_FOR_UNRETAINED(wl_surface)
#define BASE_INTERNAL_SAFE_FOR_UNRETAINED(x) struct x;
BASE_INTERNAL_LIST_OF_SAFE_FOR_UNRETAINED
#undef BASE_INTERNAL_SAFE_FOR_UNRETAINED
namespace base::internal {
template <typename T>
concept SafeIncompleteTypeForUnretained =
SameAsAny<std::remove_cvref_t<T>,
#define BASE_INTERNAL_SAFE_FOR_UNRETAINED(x) x,
BASE_INTERNAL_LIST_OF_SAFE_FOR_UNRETAINED
#undef BASE_INTERNAL_SAFE_FOR_UNRETAINED
void>;
template <typename T>
inline constexpr bool kCustomizeSupportsUnretained = true;
template <typename T>
concept DisallowsUnretained = !kCustomizeSupportsUnretained<T> || requires {
typename T::DisallowBaseUnretainedMarker;
};
template <typename T>
struct SupportsUnretainedImpl {
template <bool v = IsComplete<T> || SafeIncompleteTypeForUnretained<T>>
struct AllowlistIncompleteTypes {
static constexpr bool value = [] {
#if defined(FORCE_UNRETAINED_COMPLETENESS_CHECKS_FOR_TESTS) || \
(!defined(UNIT_TEST) && !defined(OFFICIAL_BUILD) && \
(BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_WIN)))
static_assert(v,
"Argument requires unretained storage, but type is not "
"fully defined. This prevents determining whether "
"`Unretained()` is supported.");
return v;
#else
return true;
#endif
}();
};
template <bool v = !DisallowsUnretained<T>>
struct AllowsUnretained {
static constexpr bool value = [] {
static_assert(v,
"Argument requires unretained storage, but type does not "
"support `Unretained()`. See "
"base/functional/disallow_unretained.h for alternatives.");
return v;
}();
};
static constexpr bool value =
std::conjunction_v<AllowlistIncompleteTypes<>, AllowsUnretained<>>;
};
template <typename T>
concept SupportsUnretained = SupportsUnretainedImpl<T>::value;
}
#endif