[INFRA] Import NVIDIA/CCCL upstream as optimization reference library
CCCL (CUDA C++ Core Libraries) provides: - CUB: device/block/warp-level GPU primitives (reduce, scan, sort, topk) - Thrust: high-level parallel algorithms (transform_reduce, sort, scan) - libcudacxx: CUDA C++ standard library (atomics, barriers, memory) - cudax: experimental features (memory resources, allocators) - Tuning policies: per-SM hardware-specific algorithm parameters Competition optimization vectors mapped to CCCL: - Output TPS (83% weight): warp_reduce, block_reduce, device_topk - Input TPS (14% weight): device_scan, block_load, prefetch - Cache TPS (3% weight): prefix caching strategy patterns - Memory (0.9 util): pooled/cached/buddy allocators Source: https://github.com/NVIDIA/cccl (shallow clone, HEAD only) License: Apache-2.0
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of libcu++, the C++ Standard Library for your entire system,
|
||||
// under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
// SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef _CUDA___UTILITY_BASIC_ANY_ACCESS_H
|
||||
#define _CUDA___UTILITY_BASIC_ANY_ACCESS_H
|
||||
|
||||
#include <cuda/std/detail/__config>
|
||||
|
||||
#if defined(_CCCL_IMPLICIT_SYSTEM_HEADER_GCC)
|
||||
# pragma GCC system_header
|
||||
#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_CLANG)
|
||||
# pragma clang system_header
|
||||
#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_MSVC)
|
||||
# pragma system_header
|
||||
#endif // no system header
|
||||
|
||||
#include <cuda/__type_traits/is_specialization_of.h>
|
||||
#include <cuda/__utility/__basic_any/basic_any_fwd.h>
|
||||
#include <cuda/__utility/__basic_any/conversions.h>
|
||||
#include <cuda/__utility/__basic_any/interfaces.h>
|
||||
#include <cuda/std/__concepts/concept_macros.h>
|
||||
#include <cuda/std/__type_traits/remove_const.h>
|
||||
#include <cuda/std/__type_traits/remove_cvref.h>
|
||||
|
||||
#include <cuda/std/__cccl/prologue.h>
|
||||
|
||||
_CCCL_BEGIN_NAMESPACE_CUDA
|
||||
|
||||
//!
|
||||
//! __basic_any_access
|
||||
//!
|
||||
struct __basic_any_access
|
||||
{
|
||||
template <class _Interface>
|
||||
_CCCL_NODEBUG_API static auto __make() noexcept -> __basic_any<_Interface>
|
||||
{
|
||||
return __basic_any<_Interface>{};
|
||||
}
|
||||
|
||||
_CCCL_TEMPLATE(class _SrcCvAny, class _DstInterface)
|
||||
_CCCL_REQUIRES(__any_castable_to<_SrcCvAny, __basic_any<_DstInterface>>)
|
||||
_CCCL_NODEBUG_API static auto __cast_to(_SrcCvAny&& __from, __basic_any<_DstInterface>& __to) noexcept(
|
||||
noexcept(__to.__convert_from(static_cast<_SrcCvAny&&>(__from)))) -> void
|
||||
{
|
||||
static_assert(__is_specialization_of_v<::cuda::std::remove_cvref_t<_SrcCvAny>, __basic_any>);
|
||||
__to.__convert_from(static_cast<_SrcCvAny&&>(__from));
|
||||
}
|
||||
|
||||
_CCCL_TEMPLATE(class _SrcCvAny, class _DstInterface)
|
||||
_CCCL_REQUIRES(__any_castable_to<_SrcCvAny*, __basic_any<_DstInterface>>)
|
||||
_CCCL_NODEBUG_API static auto
|
||||
__cast_to(_SrcCvAny* __from, __basic_any<_DstInterface>& __to) noexcept(noexcept(__to.__convert_from(__from))) -> void
|
||||
{
|
||||
static_assert(__is_specialization_of_v<::cuda::std::remove_const_t<_SrcCvAny>, __basic_any>);
|
||||
__to.__convert_from(__from);
|
||||
}
|
||||
|
||||
template <class _Interface>
|
||||
_CCCL_NODEBUG_API static auto __get_vptr(__basic_any<_Interface> const& __self) noexcept -> __vptr_for<_Interface>
|
||||
{
|
||||
return __self.__get_vptr();
|
||||
}
|
||||
|
||||
template <class _Interface>
|
||||
_CCCL_NODEBUG_API static auto __get_optr(__basic_any<_Interface>& __self) noexcept -> void*
|
||||
{
|
||||
return __self.__get_optr();
|
||||
}
|
||||
|
||||
template <class _Interface>
|
||||
_CCCL_NODEBUG_API static auto __get_optr(__basic_any<_Interface> const& __self) noexcept -> void const*
|
||||
{
|
||||
return __self.__get_optr();
|
||||
}
|
||||
};
|
||||
|
||||
_CCCL_END_NAMESPACE_CUDA
|
||||
|
||||
#include <cuda/std/__cccl/epilogue.h>
|
||||
|
||||
#endif // _CUDA___UTILITY_BASIC_ANY_ACCESS_H
|
||||
@@ -0,0 +1,83 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of libcu++, the C++ Standard Library for your entire system,
|
||||
// under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
// SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef _CUDA___UTILITY_BASIC_ANY_ANY_CAST_H
|
||||
#define _CUDA___UTILITY_BASIC_ANY_ANY_CAST_H
|
||||
|
||||
#include <cuda/std/detail/__config>
|
||||
|
||||
#if defined(_CCCL_IMPLICIT_SYSTEM_HEADER_GCC)
|
||||
# pragma GCC system_header
|
||||
#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_CLANG)
|
||||
# pragma clang system_header
|
||||
#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_MSVC)
|
||||
# pragma system_header
|
||||
#endif // no system header
|
||||
|
||||
#include <cuda/__utility/__basic_any/access.h>
|
||||
#include <cuda/__utility/__basic_any/basic_any_fwd.h>
|
||||
#include <cuda/__utility/__basic_any/interfaces.h>
|
||||
#include <cuda/std/__concepts/concept_macros.h>
|
||||
#include <cuda/std/__type_traits/is_const.h>
|
||||
#include <cuda/std/__type_traits/is_void.h>
|
||||
#include <cuda/std/__utility/move.h>
|
||||
#include <cuda/std/__utility/typeid.h>
|
||||
|
||||
#include <cuda/std/__cccl/prologue.h>
|
||||
|
||||
_CCCL_BEGIN_NAMESPACE_CUDA
|
||||
|
||||
//!
|
||||
//! __valid_any_cast
|
||||
//!
|
||||
template <class _Interface, class _Tp>
|
||||
inline constexpr bool __valid_any_cast = true;
|
||||
|
||||
template <class _Interface, class _Tp>
|
||||
inline constexpr bool __valid_any_cast<_Interface*, _Tp> = false;
|
||||
|
||||
template <class _Interface, class _Tp>
|
||||
inline constexpr bool __valid_any_cast<_Interface*, _Tp*> =
|
||||
!::cuda::std::is_const_v<_Interface> || ::cuda::std::is_const_v<_Tp>;
|
||||
|
||||
//!
|
||||
//! __any_cast
|
||||
//!
|
||||
_CCCL_TEMPLATE(class _Tp, class _Interface)
|
||||
_CCCL_REQUIRES(__satisfies<_Tp, _Interface> || ::cuda::std::is_void_v<_Tp>)
|
||||
[[nodiscard]] _CCCL_HOST_DEVICE_API auto __any_cast(__basic_any<_Interface>* __self) noexcept -> _Tp*
|
||||
{
|
||||
static_assert(__valid_any_cast<_Interface, _Tp>);
|
||||
if (__self && (::cuda::std::is_void_v<_Tp> || __self->type() == _CCCL_TYPEID(_Tp)))
|
||||
{
|
||||
return static_cast<_Tp*>(__basic_any_access::__get_optr(*__self));
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
_CCCL_TEMPLATE(class _Tp, class _Interface)
|
||||
_CCCL_REQUIRES(__satisfies<_Tp, _Interface> || ::cuda::std::is_void_v<_Tp>)
|
||||
[[nodiscard]] _CCCL_HOST_DEVICE_API auto __any_cast(__basic_any<_Interface> const* __self) noexcept -> _Tp const*
|
||||
{
|
||||
static_assert(__valid_any_cast<_Interface, _Tp>);
|
||||
if (__self && (::cuda::std::is_void_v<_Tp> || __self->type() == _CCCL_TYPEID(_Tp)))
|
||||
{
|
||||
return static_cast<_Tp const*>(__basic_any_access::__get_optr(*__self));
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// TODO: implement the same overloads as for std::__any_cast
|
||||
|
||||
_CCCL_END_NAMESPACE_CUDA
|
||||
|
||||
#include <cuda/std/__cccl/epilogue.h>
|
||||
|
||||
#endif // _CUDA___UTILITY_BASIC_ANY_ANY_CAST_H
|
||||
@@ -0,0 +1,131 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of libcu++, the C++ Standard Library for your entire system,
|
||||
// under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
// SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef _CUDA___UTILITY_BASIC_ANY_BASIC_ANY_BASE_H
|
||||
#define _CUDA___UTILITY_BASIC_ANY_BASIC_ANY_BASE_H
|
||||
|
||||
#include <cuda/std/detail/__config>
|
||||
|
||||
#if defined(_CCCL_IMPLICIT_SYSTEM_HEADER_GCC)
|
||||
# pragma GCC system_header
|
||||
#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_CLANG)
|
||||
# pragma clang system_header
|
||||
#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_MSVC)
|
||||
# pragma system_header
|
||||
#endif // no system header
|
||||
|
||||
#include <cuda/__utility/__basic_any/basic_any_fwd.h>
|
||||
#include <cuda/__utility/__basic_any/interfaces.h>
|
||||
#include <cuda/__utility/__basic_any/storage.h>
|
||||
#include <cuda/__utility/__basic_any/tagged_ptr.h>
|
||||
#include <cuda/std/__concepts/concept_macros.h>
|
||||
#include <cuda/std/__type_traits/remove_cvref.h>
|
||||
#include <cuda/std/cstddef> // for byte
|
||||
|
||||
#include <cuda/std/__cccl/prologue.h>
|
||||
|
||||
_CCCL_BEGIN_NAMESPACE_CUDA
|
||||
|
||||
template <class _Interface>
|
||||
_CCCL_HOST_DEVICE_API auto __is_basic_any_test(__basic_any<_Interface>&&) -> __basic_any<_Interface>&&;
|
||||
template <class _Interface>
|
||||
_CCCL_HOST_DEVICE_API auto __is_basic_any_test(__basic_any<_Interface>&) -> __basic_any<_Interface>&;
|
||||
template <class _Interface>
|
||||
_CCCL_HOST_DEVICE_API auto __is_basic_any_test(__basic_any<_Interface> const&) -> __basic_any<_Interface> const&;
|
||||
|
||||
#if _CCCL_COMPILER(CLANG, <, 12) || _CCCL_COMPILER(GCC, <, 11)
|
||||
// Older versions of clang and gcc need help disambiguating between
|
||||
// __basic_any<__ireference<I>> and __basic_any<I&>.
|
||||
template <class _Interface>
|
||||
_CCCL_HOST_DEVICE_API auto __is_basic_any_test(__basic_any<_Interface&>&&) -> __basic_any<_Interface&>&&;
|
||||
template <class _Interface>
|
||||
_CCCL_HOST_DEVICE_API auto __is_basic_any_test(__basic_any<_Interface&>&) -> __basic_any<_Interface&>&;
|
||||
template <class _Interface>
|
||||
_CCCL_HOST_DEVICE_API auto __is_basic_any_test(__basic_any<_Interface&> const&) -> __basic_any<_Interface&> const&;
|
||||
#endif
|
||||
|
||||
// clang-format off
|
||||
template <class _Tp>
|
||||
_CCCL_CONCEPT __is_basic_any =
|
||||
_CCCL_REQUIRES_EXPR((_Tp), _Tp& __value)
|
||||
(
|
||||
(::cuda::__is_basic_any_test(__value))
|
||||
);
|
||||
// clang-format on
|
||||
|
||||
// We need a base class to correctly implement movability and copyability.
|
||||
template <class _Interface, int = __extension_of<_Interface, __imovable<>> + __extension_of<_Interface, __icopyable<>>>
|
||||
struct __basic_any_base;
|
||||
|
||||
template <class _Interface>
|
||||
struct __basic_any_base<_Interface, 2> : __interface_of<_Interface> // copyable interfaces
|
||||
{
|
||||
__basic_any_base() = default;
|
||||
|
||||
_CCCL_HOST_DEVICE_API __basic_any_base(__basic_any_base&& __other) noexcept
|
||||
{
|
||||
static_cast<__basic_any<_Interface>*>(this)->__convert_from(static_cast<__basic_any<_Interface>&&>(__other));
|
||||
}
|
||||
|
||||
_CCCL_HOST_DEVICE_API __basic_any_base(__basic_any_base const& __other)
|
||||
{
|
||||
static_cast<__basic_any<_Interface>*>(this)->__convert_from(static_cast<__basic_any<_Interface> const&>(__other));
|
||||
}
|
||||
|
||||
_CCCL_HOST_DEVICE_API auto operator=(__basic_any_base&& __other) noexcept -> __basic_any_base&
|
||||
{
|
||||
static_cast<__basic_any<_Interface>*>(this)->__assign_from(static_cast<__basic_any<_Interface>&&>(__other));
|
||||
return *this;
|
||||
}
|
||||
|
||||
// NOLINTNEXTLINE(bugprone-unhandled-self-assignment): yes it does (__assign_from does)
|
||||
_CCCL_HOST_DEVICE_API auto operator=(__basic_any_base const& __other) -> __basic_any_base&
|
||||
{
|
||||
static_cast<__basic_any<_Interface>*>(this)->__assign_from(static_cast<__basic_any<_Interface> const&>(__other));
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
template <class>
|
||||
friend struct __basic_any;
|
||||
friend struct __basic_any_access;
|
||||
|
||||
static constexpr size_t __size_ = __buffer_size(_Interface::size);
|
||||
static constexpr size_t __align_ = __buffer_align(_Interface::align);
|
||||
|
||||
__tagged_ptr<__vptr_for<_Interface>> __vptr_{};
|
||||
alignas(__align_)::cuda::std::byte __buffer_[__size_];
|
||||
};
|
||||
|
||||
template <class _Interface>
|
||||
struct __basic_any_base<_Interface, 1> : __basic_any_base<_Interface, 2> // move-only interfaces
|
||||
{
|
||||
__basic_any_base() = default;
|
||||
__basic_any_base(__basic_any_base&&) noexcept = default;
|
||||
__basic_any_base(__basic_any_base const&) = delete;
|
||||
auto operator=(__basic_any_base&&) noexcept -> __basic_any_base& = default;
|
||||
auto operator=(__basic_any_base const&) -> __basic_any_base& = delete;
|
||||
};
|
||||
|
||||
template <class _Interface>
|
||||
struct __basic_any_base<_Interface, 0> : __basic_any_base<_Interface, 2> // immovable interfaces
|
||||
{
|
||||
__basic_any_base() = default;
|
||||
__basic_any_base(__basic_any_base&&) noexcept = delete;
|
||||
__basic_any_base(__basic_any_base const&) = delete;
|
||||
auto operator=(__basic_any_base&&) noexcept -> __basic_any_base& = delete;
|
||||
auto operator=(__basic_any_base const&) -> __basic_any_base& = delete;
|
||||
};
|
||||
|
||||
_CCCL_END_NAMESPACE_CUDA
|
||||
|
||||
#include <cuda/std/__cccl/epilogue.h>
|
||||
|
||||
#endif // _CUDA___UTILITY_BASIC_ANY_BASIC_ANY_BASE_H
|
||||
@@ -0,0 +1,98 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of libcu++, the C++ Standard Library for your entire system,
|
||||
// under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
// SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef _CUDA___UTILITY_BASIC_ANY_BASIC_ANY_FROM_H
|
||||
#define _CUDA___UTILITY_BASIC_ANY_BASIC_ANY_FROM_H
|
||||
|
||||
#include <cuda/std/detail/__config>
|
||||
|
||||
#if defined(_CCCL_IMPLICIT_SYSTEM_HEADER_GCC)
|
||||
# pragma GCC system_header
|
||||
#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_CLANG)
|
||||
# pragma clang system_header
|
||||
#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_MSVC)
|
||||
# pragma system_header
|
||||
#endif // no system header
|
||||
|
||||
#include <cuda/__utility/__basic_any/basic_any_fwd.h>
|
||||
#include <cuda/std/__type_traits/decay.h>
|
||||
#include <cuda/std/__utility/declval.h>
|
||||
|
||||
#include <cuda/std/__cccl/prologue.h>
|
||||
|
||||
_CCCL_BEGIN_NAMESPACE_CUDA
|
||||
|
||||
//!
|
||||
//! `__basic_any_from`
|
||||
//!
|
||||
//! \brief This function is for use in the thunks in an interface to get
|
||||
//! a pointer or a reference to the full `__basic_any` object.
|
||||
//!
|
||||
template <template <class...> class _Interface, class _Super>
|
||||
[[nodiscard]] _CCCL_NODEBUG_API auto __basic_any_from(_Interface<_Super>&& __self) noexcept -> __basic_any<_Super>&&
|
||||
{
|
||||
return static_cast<__basic_any<_Super>&&>(__self);
|
||||
}
|
||||
|
||||
template <template <class...> class _Interface, class _Super>
|
||||
[[nodiscard]] _CCCL_NODEBUG_API auto __basic_any_from(_Interface<_Super>& __self) noexcept -> __basic_any<_Super>&
|
||||
{
|
||||
return static_cast<__basic_any<_Super>&>(__self);
|
||||
}
|
||||
|
||||
template <template <class...> class _Interface, class _Super>
|
||||
[[nodiscard]] _CCCL_NODEBUG_API auto __basic_any_from(_Interface<_Super> const& __self) noexcept
|
||||
-> __basic_any<_Super> const&
|
||||
{
|
||||
return static_cast<__basic_any<_Super> const&>(__self);
|
||||
}
|
||||
|
||||
template <template <class...> class _Interface>
|
||||
[[nodiscard]] _CCCL_HOST_DEVICE_API auto __basic_any_from(_Interface<> const&) noexcept
|
||||
-> __basic_any<_Interface<>> const&
|
||||
{
|
||||
// This overload is selected when called from the thunk of an unspecialized
|
||||
// interface; e.g., `icat<>` rather than `icat<ialley_cat<>>`. The thunks of
|
||||
// unspecialized interfaces are never called, they just need to exist.
|
||||
_CCCL_UNREACHABLE();
|
||||
}
|
||||
|
||||
template <template <class...> class _Interface, class _Super>
|
||||
[[nodiscard]] _CCCL_NODEBUG_API auto __basic_any_from(_Interface<_Super>* __self) noexcept -> __basic_any<_Super>*
|
||||
{
|
||||
return static_cast<__basic_any<_Super>*>(__self);
|
||||
}
|
||||
|
||||
template <template <class...> class _Interface, class _Super>
|
||||
[[nodiscard]] _CCCL_NODEBUG_API auto __basic_any_from(_Interface<_Super> const* __self) noexcept
|
||||
-> __basic_any<_Super> const*
|
||||
{
|
||||
return static_cast<__basic_any<_Super> const*>(__self);
|
||||
}
|
||||
|
||||
template <template <class...> class _Interface>
|
||||
[[nodiscard]] _CCCL_HOST_DEVICE_API auto __basic_any_from(_Interface<> const*) noexcept
|
||||
-> __basic_any<_Interface<>> const*
|
||||
{
|
||||
// See comment above about the use of `__basic_any_from` in the thunks of
|
||||
// unspecialized interfaces.
|
||||
_CCCL_UNREACHABLE();
|
||||
}
|
||||
|
||||
template <class _CvInterface>
|
||||
using __cvref_basic_any_from_t = decltype(::cuda::__basic_any_from(::cuda::std::declval<_CvInterface>()));
|
||||
|
||||
template <class _CvInterface>
|
||||
using __basic_any_from_t = ::cuda::std::decay_t<__cvref_basic_any_from_t<_CvInterface>>;
|
||||
_CCCL_END_NAMESPACE_CUDA
|
||||
|
||||
#include <cuda/std/__cccl/epilogue.h>
|
||||
|
||||
#endif // _CUDA___UTILITY_BASIC_ANY_BASIC_ANY_FROM_H
|
||||
@@ -0,0 +1,128 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of libcu++, the C++ Standard Library for your entire system,
|
||||
// under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
// SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef _CUDA___UTILITY_BASIC_ANY_FWD_H
|
||||
#define _CUDA___UTILITY_BASIC_ANY_FWD_H
|
||||
|
||||
#include <cuda/std/detail/__config>
|
||||
|
||||
#if defined(_CCCL_IMPLICIT_SYSTEM_HEADER_GCC)
|
||||
# pragma GCC system_header
|
||||
#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_CLANG)
|
||||
# pragma clang system_header
|
||||
#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_MSVC)
|
||||
# pragma system_header
|
||||
#endif // no system header
|
||||
|
||||
#include <cuda/std/__type_traits/integral_constant.h>
|
||||
#include <cuda/std/__type_traits/type_list.h>
|
||||
#include <cuda/std/cstddef> // for max_align_t
|
||||
#include <cuda/std/cstdint> // for uint8_t
|
||||
|
||||
#include <cuda/std/__cccl/prologue.h>
|
||||
|
||||
_CCCL_BEGIN_NAMESPACE_CUDA
|
||||
|
||||
template <class _Interface>
|
||||
struct __ireference;
|
||||
|
||||
template <class _Interface>
|
||||
struct _CCCL_TYPE_VISIBILITY_DEFAULT __basic_any;
|
||||
|
||||
template <class _Interface>
|
||||
struct _CCCL_DECLSPEC_EMPTY_BASES __basic_any<__ireference<_Interface>>;
|
||||
|
||||
template <class _Interface>
|
||||
struct __basic_any<_Interface*>;
|
||||
|
||||
template <class _Interface>
|
||||
struct __basic_any<_Interface&>;
|
||||
|
||||
template <auto _Value>
|
||||
using __constant = ::cuda::std::integral_constant<decltype(_Value), _Value>;
|
||||
|
||||
template <class _InterfaceOrModel, class... _VirtualFnsOrOverrides>
|
||||
struct __overrides_list;
|
||||
|
||||
template <class _InterfaceOrModel, auto... _VirtualFnsOrOverrides>
|
||||
using __overrides_for = __overrides_list<_InterfaceOrModel, __constant<_VirtualFnsOrOverrides>...>;
|
||||
|
||||
template <class _Interface, auto... _Mbrs>
|
||||
struct _CCCL_DECLSPEC_EMPTY_BASES __basic_vtable;
|
||||
|
||||
struct __rtti_base;
|
||||
|
||||
struct __rtti;
|
||||
|
||||
template <size_t NbrBases>
|
||||
struct __rtti_ex;
|
||||
|
||||
template <class...>
|
||||
struct __extends;
|
||||
|
||||
template <template <class...> class, class = __extends<>, size_t = 0, size_t = 0>
|
||||
struct __basic_interface;
|
||||
|
||||
template <class _Interface, class... _Super>
|
||||
using __rebind_interface _CCCL_NODEBUG_ALIAS = typename _Interface::template __rebind<_Super...>;
|
||||
|
||||
struct __iunknown;
|
||||
|
||||
template <class...>
|
||||
struct __iset_;
|
||||
|
||||
template <class...>
|
||||
struct __iset_vptr;
|
||||
|
||||
template <class...>
|
||||
struct __imovable;
|
||||
|
||||
template <class...>
|
||||
struct __icopyable;
|
||||
|
||||
template <class...>
|
||||
struct __iequality_comparable;
|
||||
|
||||
template <class... _Tp>
|
||||
using __tag _CCCL_NODEBUG_ALIAS = ::cuda::std::__type_list_ptr<_Tp...>;
|
||||
|
||||
template <auto...>
|
||||
struct __ctag_;
|
||||
|
||||
template <auto... _Is>
|
||||
using __ctag _CCCL_NODEBUG_ALIAS = __ctag_<_Is...>*;
|
||||
|
||||
constexpr size_t __word = sizeof(void*);
|
||||
constexpr size_t __default_small_object_size = 3 * __word;
|
||||
constexpr size_t __default_small_object_align = alignof(::cuda::std::max_align_t);
|
||||
|
||||
using __make_type_list _CCCL_NODEBUG_ALIAS = ::cuda::std::__type_quote<::cuda::std::__type_list>;
|
||||
|
||||
[[noreturn]] _CCCL_HOST_DEVICE_API void __throw_bad_any_cast();
|
||||
|
||||
enum class __vtable_kind : uint8_t
|
||||
{
|
||||
__normal,
|
||||
__rtti,
|
||||
};
|
||||
|
||||
inline constexpr uint8_t __basic_any_version = 1;
|
||||
|
||||
template <class _Interface>
|
||||
extern _Interface __remove_ireference_v; // specialized in interfaces.cuh
|
||||
|
||||
template <class _Interface>
|
||||
using __remove_ireference_t _CCCL_NODEBUG_ALIAS = decltype(__remove_ireference_v<_Interface>);
|
||||
|
||||
_CCCL_END_NAMESPACE_CUDA
|
||||
|
||||
#include <cuda/std/__cccl/epilogue.h>
|
||||
|
||||
#endif // _CUDA___UTILITY_BASIC_ANY_FWD_H
|
||||
@@ -0,0 +1,306 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of libcu++, the C++ Standard Library for your entire system,
|
||||
// under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
// SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef _CUDA___UTILITY_BASIC_ANY_BASIC_ANY_PTR_H
|
||||
#define _CUDA___UTILITY_BASIC_ANY_BASIC_ANY_PTR_H
|
||||
|
||||
#include <cuda/std/detail/__config>
|
||||
|
||||
#if defined(_CCCL_IMPLICIT_SYSTEM_HEADER_GCC)
|
||||
# pragma GCC system_header
|
||||
#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_CLANG)
|
||||
# pragma clang system_header
|
||||
#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_MSVC)
|
||||
# pragma system_header
|
||||
#endif // no system header
|
||||
|
||||
#include <cuda/__utility/__basic_any/basic_any_base.h>
|
||||
#include <cuda/__utility/__basic_any/basic_any_from.h>
|
||||
#include <cuda/__utility/__basic_any/basic_any_fwd.h>
|
||||
#include <cuda/__utility/__basic_any/basic_any_ref.h>
|
||||
#include <cuda/__utility/__basic_any/conversions.h>
|
||||
#include <cuda/__utility/__basic_any/interfaces.h>
|
||||
#include <cuda/__utility/__basic_any/rtti.h>
|
||||
#include <cuda/__utility/__basic_any/virtual_tables.h>
|
||||
#include <cuda/std/__concepts/concept_macros.h>
|
||||
#include <cuda/std/__concepts/derived_from.h>
|
||||
#include <cuda/std/__concepts/same_as.h>
|
||||
#include <cuda/std/__type_traits/is_const.h>
|
||||
#include <cuda/std/__type_traits/maybe_const.h>
|
||||
#include <cuda/std/__type_traits/remove_const.h>
|
||||
#include <cuda/std/__type_traits/remove_pointer.h>
|
||||
#include <cuda/std/__utility/typeid.h>
|
||||
|
||||
#include <cuda/std/__cccl/prologue.h>
|
||||
|
||||
_CCCL_BEGIN_NAMESPACE_CUDA
|
||||
|
||||
//!
|
||||
//! __basic_any<_Interface*>
|
||||
//!
|
||||
template <class _Interface>
|
||||
struct _CCCL_TYPE_VISIBILITY_DEFAULT __basic_any<_Interface*>
|
||||
{
|
||||
using interface_type = ::cuda::std::remove_const_t<_Interface>;
|
||||
static constexpr bool __is_const_ptr = ::cuda::std::is_const_v<_Interface>;
|
||||
|
||||
//!
|
||||
//! Constructors
|
||||
//!
|
||||
__basic_any() = default;
|
||||
|
||||
_CCCL_NODEBUG_API __basic_any(::cuda::std::nullptr_t) {}
|
||||
|
||||
_CCCL_TEMPLATE(class _Tp, class _Up = ::cuda::std::remove_const_t<_Tp>)
|
||||
_CCCL_REQUIRES((!__is_basic_any<_Tp>) _CCCL_AND __satisfies<_Up, interface_type> _CCCL_AND(
|
||||
__is_const_ptr || !::cuda::std::is_const_v<_Tp>))
|
||||
_CCCL_HOST_DEVICE_API __basic_any(_Tp* __obj) noexcept
|
||||
{
|
||||
operator=(__obj);
|
||||
}
|
||||
|
||||
_CCCL_HOST_DEVICE_API __basic_any(__basic_any const& __other) noexcept
|
||||
{
|
||||
__convert_from(__other);
|
||||
}
|
||||
|
||||
_CCCL_TEMPLATE(class _OtherInterface)
|
||||
_CCCL_REQUIRES((!::cuda::std::same_as<_OtherInterface, _Interface>)
|
||||
_CCCL_AND __any_convertible_to<__basic_any<_OtherInterface*>, __basic_any<_Interface*>>)
|
||||
_CCCL_HOST_DEVICE_API __basic_any(__basic_any<_OtherInterface*> const& __other) noexcept
|
||||
{
|
||||
__convert_from(__other);
|
||||
}
|
||||
|
||||
_CCCL_TEMPLATE(class _OtherInterface)
|
||||
_CCCL_REQUIRES(__any_convertible_to<__basic_any<_OtherInterface>&, __basic_any<_Interface&>>)
|
||||
_CCCL_HOST_DEVICE_API __basic_any(__basic_any<_OtherInterface>* __other) noexcept
|
||||
{
|
||||
__convert_from(__other);
|
||||
}
|
||||
|
||||
_CCCL_TEMPLATE(class _OtherInterface)
|
||||
_CCCL_REQUIRES(__any_convertible_to<__basic_any<_OtherInterface> const&, __basic_any<_Interface&>>)
|
||||
_CCCL_HOST_DEVICE_API __basic_any(__basic_any<_OtherInterface> const* __other) noexcept
|
||||
{
|
||||
__convert_from(__other);
|
||||
}
|
||||
|
||||
_CCCL_TEMPLATE(template <class...> class _OtherInterface, class _Super)
|
||||
_CCCL_REQUIRES(__is_interface<_OtherInterface<_Super>>
|
||||
_CCCL_AND ::cuda::std::derived_from<__basic_any<_Super>, _OtherInterface<_Super>>
|
||||
_CCCL_AND ::cuda::std::same_as<__normalized_interface_of<__basic_any<_Super>*>, _Interface*>)
|
||||
_CCCL_HOST_DEVICE_API explicit __basic_any(_OtherInterface<_Super>* __self) noexcept
|
||||
{
|
||||
__convert_from(__basic_any_from(__self));
|
||||
}
|
||||
|
||||
_CCCL_TEMPLATE(template <class...> class _OtherInterface, class _Super)
|
||||
_CCCL_REQUIRES(__is_interface<_OtherInterface<_Super>>
|
||||
_CCCL_AND ::cuda::std::derived_from<__basic_any<_Super>, _OtherInterface<_Super>>
|
||||
_CCCL_AND ::cuda::std::same_as<__normalized_interface_of<__basic_any<_Super> const*>, _Interface*>)
|
||||
_CCCL_HOST_DEVICE_API explicit __basic_any(_OtherInterface<_Super> const* __self) noexcept
|
||||
{
|
||||
__convert_from(__basic_any_from(__self));
|
||||
}
|
||||
|
||||
//!
|
||||
//! Assignment operators
|
||||
//!
|
||||
_CCCL_HOST_DEVICE_API auto operator=(::cuda::std::nullptr_t) noexcept -> __basic_any&
|
||||
{
|
||||
reset();
|
||||
return *this;
|
||||
}
|
||||
|
||||
_CCCL_TEMPLATE(class _Tp, class _Up = ::cuda::std::remove_const_t<_Tp>)
|
||||
_CCCL_REQUIRES((!__is_basic_any<_Tp>) _CCCL_AND //
|
||||
__satisfies<_Up, interface_type> _CCCL_AND //
|
||||
(__is_const_ptr || !::cuda::std::is_const_v<_Tp>))
|
||||
_CCCL_HOST_DEVICE_API auto operator=(_Tp* __obj) noexcept -> __basic_any&
|
||||
{
|
||||
__vptr_for<interface_type> __vptr = ::cuda::__get_vtable_ptr_for<interface_type, _Up>();
|
||||
__ref_.__set_ref(__obj ? __vptr : nullptr, __obj);
|
||||
return *this;
|
||||
}
|
||||
|
||||
_CCCL_HOST_DEVICE_API auto operator=(__basic_any const& __other) noexcept -> __basic_any&
|
||||
{
|
||||
__convert_from(__other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
_CCCL_TEMPLATE(class _OtherInterface)
|
||||
_CCCL_REQUIRES((!::cuda::std::same_as<_OtherInterface, _Interface>)
|
||||
_CCCL_AND __any_convertible_to<__basic_any<_OtherInterface*>, __basic_any<_Interface*>>)
|
||||
_CCCL_HOST_DEVICE_API auto operator=(__basic_any<_OtherInterface*> const& __other) noexcept -> __basic_any&
|
||||
{
|
||||
__convert_from(__other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
_CCCL_TEMPLATE(class _OtherInterface)
|
||||
_CCCL_REQUIRES(__any_convertible_to<__basic_any<_OtherInterface>&, __basic_any<_Interface&>>)
|
||||
_CCCL_HOST_DEVICE_API auto operator=(__basic_any<_OtherInterface>* __other) noexcept -> __basic_any&
|
||||
{
|
||||
__convert_from(__other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
_CCCL_TEMPLATE(class _OtherInterface)
|
||||
_CCCL_REQUIRES(__any_convertible_to<__basic_any<_OtherInterface> const&, __basic_any<_Interface&>>)
|
||||
_CCCL_HOST_DEVICE_API auto operator=(__basic_any<_OtherInterface> const* __other) noexcept -> __basic_any&
|
||||
{
|
||||
__convert_from(__other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//!
|
||||
//! emplace
|
||||
//!
|
||||
_CCCL_TEMPLATE(class _Tp, class _Up = ::cuda::std::remove_pointer_t<_Tp>, class _Vp = ::cuda::std::remove_const_t<_Up>)
|
||||
_CCCL_REQUIRES(__satisfies<_Vp, _Interface> _CCCL_AND(__is_const_ptr || !::cuda::std::is_const_v<_Up>))
|
||||
_CCCL_HOST_DEVICE_API auto emplace(::cuda::std::type_identity_t<_Up>* __obj) noexcept
|
||||
-> ::cuda::std::__maybe_const<__is_const_ptr, _Vp>*&
|
||||
{
|
||||
__vptr_for<interface_type> __vptr = ::cuda::__get_vtable_ptr_for<interface_type, _Vp>();
|
||||
__ref_.__set_ref(__obj ? __vptr : nullptr, __obj);
|
||||
return *reinterpret_cast<::cuda::std::__maybe_const<__is_const_ptr, _Vp>**>(&__ref_.__optr_);
|
||||
}
|
||||
|
||||
#if !defined(_CCCL_NO_THREE_WAY_COMPARISON)
|
||||
[[nodiscard]] _CCCL_HOST_DEVICE_API auto operator==(__basic_any const& __other) const noexcept -> bool
|
||||
{
|
||||
using __void_ptr_t _CCCL_NODEBUG_ALIAS = ::cuda::std::__maybe_const<__is_const_ptr, void>* const*;
|
||||
return *static_cast<__void_ptr_t>(__get_optr()) == *static_cast<__void_ptr_t>(__other.__get_optr());
|
||||
}
|
||||
#else // ^^^ !_CCCL_NO_THREE_WAY_COMPARISON ^^^ / vvv _CCCL_NO_THREE_WAY_COMPARISON vvv
|
||||
[[nodiscard]] _CCCL_HOST_DEVICE_API friend auto
|
||||
operator==(__basic_any const& __lhs, __basic_any const& __rhs) noexcept -> bool
|
||||
{
|
||||
using __void_ptr_t _CCCL_NODEBUG_ALIAS = ::cuda::std::__maybe_const<__is_const_ptr, void>* const*;
|
||||
return *static_cast<__void_ptr_t>(__lhs.__get_optr()) == *static_cast<__void_ptr_t>(__rhs.__get_optr());
|
||||
}
|
||||
|
||||
[[nodiscard]] _CCCL_NODEBUG_API friend auto operator!=(__basic_any const& __lhs, __basic_any const& __rhs) noexcept
|
||||
-> bool
|
||||
{
|
||||
return !(__lhs == __rhs);
|
||||
}
|
||||
#endif // _CCCL_NO_THREE_WAY_COMPARISON
|
||||
|
||||
using __any_ref_t _CCCL_NODEBUG_ALIAS =
|
||||
::cuda::std::__maybe_const<__is_const_ptr, __basic_any<__ireference<_Interface>>>;
|
||||
|
||||
[[nodiscard]] _CCCL_NODEBUG_API auto operator->() const noexcept -> __any_ref_t*
|
||||
{
|
||||
return &__ref_;
|
||||
}
|
||||
|
||||
[[nodiscard]] _CCCL_NODEBUG_API auto operator*() const noexcept -> __any_ref_t&
|
||||
{
|
||||
return __ref_;
|
||||
}
|
||||
|
||||
[[nodiscard]] _CCCL_HOST_DEVICE_API auto type() const noexcept -> ::cuda::std::__type_info_ref
|
||||
{
|
||||
return __ref_.__vptr_ != nullptr
|
||||
? (__is_const_ptr ? *__get_rtti()->__object_info_->__const_pointer_typeid_
|
||||
: *__get_rtti()->__object_info_->__pointer_typeid_)
|
||||
: _CCCL_TYPEID(void);
|
||||
}
|
||||
|
||||
[[nodiscard]] _CCCL_HOST_DEVICE_API auto interface() const noexcept -> ::cuda::std::__type_info_ref
|
||||
{
|
||||
return __ref_.__vptr_ != nullptr ? *__get_rtti()->__interface_typeid_ : _CCCL_TYPEID(interface_type);
|
||||
}
|
||||
|
||||
[[nodiscard]] _CCCL_HOST_DEVICE_API auto has_value() const noexcept -> bool
|
||||
{
|
||||
return __ref_.__vptr_ != nullptr;
|
||||
}
|
||||
|
||||
_CCCL_HOST_DEVICE_API void reset() noexcept
|
||||
{
|
||||
__vptr_for<interface_type> __vptr = nullptr;
|
||||
__ref_.__set_ref(__vptr, nullptr);
|
||||
}
|
||||
|
||||
[[nodiscard]] _CCCL_HOST_DEVICE_API explicit operator bool() const noexcept
|
||||
{
|
||||
return __ref_.__vptr_ != nullptr;
|
||||
}
|
||||
|
||||
#if !defined(_CCCL_DOXYGEN_INVOKED) // Do not document
|
||||
[[nodiscard]] _CCCL_NODEBUG_API static constexpr auto __in_situ() noexcept -> bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
#endif // _CCCL_DOXYGEN_INVOKED
|
||||
|
||||
private:
|
||||
template <class>
|
||||
friend struct __basic_any;
|
||||
friend struct __basic_any_access;
|
||||
|
||||
template <class _SrcCvAny>
|
||||
_CCCL_HOST_DEVICE_API void __convert_from(_SrcCvAny* __other) noexcept
|
||||
{
|
||||
__other ? __ref_.__set_ref(__other->__get_vptr(), __other->__get_optr()) : reset();
|
||||
}
|
||||
|
||||
template <class _OtherInterface>
|
||||
_CCCL_HOST_DEVICE_API void __convert_from(__basic_any<_OtherInterface*> const& __other) noexcept
|
||||
{
|
||||
using __other_interface_t _CCCL_NODEBUG_ALIAS = ::cuda::std::remove_const_t<_OtherInterface>;
|
||||
auto __to_vptr = __try_vptr_cast<__other_interface_t, interface_type>(__other.__get_vptr());
|
||||
auto __to_optr = __to_vptr ? *__other.__get_optr() : nullptr;
|
||||
__ref_.__set_ref(__to_vptr, __to_optr);
|
||||
}
|
||||
|
||||
[[nodiscard]] _CCCL_HOST_DEVICE_API auto __get_optr() noexcept -> ::cuda::std::__maybe_const<__is_const_ptr, void>**
|
||||
{
|
||||
return &__ref_.__optr_;
|
||||
}
|
||||
|
||||
[[nodiscard]] _CCCL_HOST_DEVICE_API auto __get_optr() const noexcept
|
||||
-> ::cuda::std::__maybe_const<__is_const_ptr, void>* const*
|
||||
{
|
||||
return &__ref_.__optr_;
|
||||
}
|
||||
|
||||
[[nodiscard]] _CCCL_HOST_DEVICE_API auto __get_vptr() const noexcept -> __vptr_for<interface_type>
|
||||
{
|
||||
return __ref_.__vptr_;
|
||||
}
|
||||
|
||||
[[nodiscard]] _CCCL_HOST_DEVICE_API auto __get_rtti() const noexcept -> __rtti const*
|
||||
{
|
||||
return __ref_.__vptr_ ? __ref_.__vptr_->__query_interface(__iunknown()) : nullptr;
|
||||
}
|
||||
|
||||
mutable __basic_any<__ireference<_Interface>> __ref_;
|
||||
};
|
||||
|
||||
_CCCL_TEMPLATE(template <class...> class _Interface, class _Super)
|
||||
_CCCL_REQUIRES(__is_interface<_Interface<_Super>>)
|
||||
_CCCL_DEDUCTION_GUIDE_ATTRIBUTES __basic_any(_Interface<_Super>*) //
|
||||
-> __basic_any<__normalized_interface_of<__basic_any<_Super>*>>;
|
||||
|
||||
_CCCL_TEMPLATE(template <class...> class _Interface, class _Super)
|
||||
_CCCL_REQUIRES(__is_interface<_Interface<_Super>>)
|
||||
_CCCL_DEDUCTION_GUIDE_ATTRIBUTES __basic_any(_Interface<_Super> const*) //
|
||||
-> __basic_any<__normalized_interface_of<__basic_any<_Super> const*>>;
|
||||
|
||||
_CCCL_END_NAMESPACE_CUDA
|
||||
|
||||
#include <cuda/std/__cccl/epilogue.h>
|
||||
|
||||
#endif // _CUDA___UTILITY_BASIC_ANY_BASIC_ANY_PTR_H
|
||||
@@ -0,0 +1,324 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of libcu++, the C++ Standard Library for your entire system,
|
||||
// under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
// SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef _CUDA___UTILITY_BASIC_ANY_BASIC_ANY_REF_H
|
||||
#define _CUDA___UTILITY_BASIC_ANY_BASIC_ANY_REF_H
|
||||
|
||||
#include <cuda/std/detail/__config>
|
||||
|
||||
#if defined(_CCCL_IMPLICIT_SYSTEM_HEADER_GCC)
|
||||
# pragma GCC system_header
|
||||
#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_CLANG)
|
||||
# pragma clang system_header
|
||||
#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_MSVC)
|
||||
# pragma system_header
|
||||
#endif // no system header
|
||||
|
||||
#include <cuda/__utility/__basic_any/basic_any_base.h>
|
||||
#include <cuda/__utility/__basic_any/basic_any_fwd.h>
|
||||
#include <cuda/__utility/__basic_any/conversions.h>
|
||||
#include <cuda/__utility/__basic_any/interfaces.h>
|
||||
#include <cuda/__utility/__basic_any/iset.h>
|
||||
#include <cuda/__utility/__basic_any/rtti.h>
|
||||
#include <cuda/std/__concepts/concept_macros.h>
|
||||
#include <cuda/std/__concepts/same_as.h>
|
||||
#include <cuda/std/__type_traits/is_const.h>
|
||||
#include <cuda/std/__type_traits/maybe_const.h>
|
||||
#include <cuda/std/__type_traits/remove_const.h>
|
||||
#include <cuda/std/__type_traits/remove_reference.h>
|
||||
#include <cuda/std/__utility/typeid.h>
|
||||
|
||||
#include <cuda/std/__cccl/prologue.h>
|
||||
|
||||
_CCCL_BEGIN_NAMESPACE_CUDA
|
||||
|
||||
//!
|
||||
//! \c __ireference<_Interface>
|
||||
//!
|
||||
//! For an interface `I`, `__ireference<I>` represents a reference to an object
|
||||
//! that satisfies the given interface. When you dereference a `__basic_any<I*>`,
|
||||
//! you get a `__basic_any<__ireference<I>>`. Also, `__basic_any<I&>` is implemented
|
||||
//! in terms of `__basic_any<__ireference<I>>`.
|
||||
//!
|
||||
//! Note: a `__basic_any<__ireference<_Interface>> &&` is an rvalue reference,
|
||||
//! whereas a `__basic_any<_Interface &> &&` is an lvalue reference.
|
||||
template <class _Interface>
|
||||
struct __ireference : ::cuda::std::remove_const_t<_Interface>
|
||||
{
|
||||
static_assert(::cuda::std::is_class_v<_Interface>, "expected a class type");
|
||||
static constexpr size_t __size_ = sizeof(void*);
|
||||
static constexpr size_t __align_ = alignof(void*);
|
||||
static constexpr bool __is_const_ref = ::cuda::std::is_const_v<_Interface>;
|
||||
|
||||
using interface _CCCL_NODEBUG_ALIAS = ::cuda::std::remove_const_t<_Interface>;
|
||||
};
|
||||
|
||||
//!
|
||||
//! A base class for __basic_any<__ireference<_Interface>> that provides a
|
||||
//! conversion to __basic_any<__ireference<_Interface const>>. Only used
|
||||
//! when concepts are not available.
|
||||
//!
|
||||
template <class _Interface>
|
||||
struct __basic_any_reference_conversion_base
|
||||
{
|
||||
[[nodiscard]] _CCCL_HOST_DEVICE_API operator __basic_any<__ireference<_Interface const>>() const noexcept
|
||||
{
|
||||
return __basic_any<__ireference<_Interface const>>(
|
||||
static_cast<__basic_any<__ireference<_Interface>> const&>(*this));
|
||||
}
|
||||
};
|
||||
|
||||
template <class _Interface>
|
||||
struct __basic_any_reference_conversion_base<_Interface const>
|
||||
{};
|
||||
|
||||
_CCCL_DIAG_PUSH
|
||||
// "operator __basic_any<...> will not be called for implicit or explicit conversions"
|
||||
_CCCL_DIAG_SUPPRESS_NVHPC(conversion_function_not_usable)
|
||||
// "operator __basic_any<...> will not be called for implicit or explicit conversions"
|
||||
_CCCL_BEGIN_NV_DIAG_SUPPRESS(554)
|
||||
|
||||
//!
|
||||
//! \c __basic_any<__ireference<_Interface>>
|
||||
//!
|
||||
//! A `__basic_any<__ireference<_Interface>>` is a reference to an object that
|
||||
//! satisfies the given interface. It is used as the result of dereferencing
|
||||
//! a `__basic_any<_Interface*>` and as the implementation of
|
||||
//! `__basic_any<_Interface&>`.
|
||||
//!
|
||||
//! `__basic_any<__ireference<_Interface>>` is neither copyable nor movable. It is
|
||||
//! not an end-user type.
|
||||
template <class _Interface>
|
||||
struct _CCCL_DECLSPEC_EMPTY_BASES __basic_any<__ireference<_Interface>>
|
||||
: __interface_of<__ireference<_Interface>>
|
||||
, __basic_any_reference_conversion_base<_Interface>
|
||||
{
|
||||
static_assert(::cuda::std::is_class_v<_Interface>, "expecting a class type");
|
||||
using interface_type = ::cuda::std::remove_const_t<_Interface>;
|
||||
static constexpr bool __is_const_ref = ::cuda::std::is_const_v<_Interface>;
|
||||
|
||||
__basic_any(__basic_any&&) = delete;
|
||||
__basic_any(__basic_any const&) = delete;
|
||||
|
||||
auto operator=(__basic_any&&) -> __basic_any& = delete;
|
||||
auto operator=(__basic_any const&) -> __basic_any& = delete;
|
||||
|
||||
//! \brief Returns a const reference to the type_info for the decayed type
|
||||
//! of the type-erased object.
|
||||
[[nodiscard]] _CCCL_HOST_DEVICE_API auto type() const noexcept -> ::cuda::std::__type_info_ref
|
||||
{
|
||||
return *__get_rtti()->__object_info_->__object_typeid_;
|
||||
}
|
||||
|
||||
//! \brief Returns a const reference to the type_info for the decayed type
|
||||
//! of the type-erased object.
|
||||
[[nodiscard]] _CCCL_HOST_DEVICE_API auto interface() const noexcept -> ::cuda::std::__type_info_ref
|
||||
{
|
||||
return *__get_rtti()->__interface_typeid_;
|
||||
}
|
||||
|
||||
//! \brief Returns a reference to a type_info object representing the type of
|
||||
//! the dynamic interface.
|
||||
//!
|
||||
//! The dynamic interface is the interface that was used to construct the
|
||||
//! object, which may be different from the current object's interface if
|
||||
//! there was a conversion.
|
||||
[[nodiscard]] _CCCL_NODEBUG_API static constexpr auto has_value() noexcept -> bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
#if !defined(_CCCL_DOXYGEN_INVOKED) // Do not document
|
||||
[[nodiscard]] _CCCL_NODEBUG_API static constexpr auto __in_situ() noexcept -> bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
#endif // _CCCL_DOXYGEN_INVOKED
|
||||
|
||||
private:
|
||||
template <class>
|
||||
friend struct __basic_any;
|
||||
friend struct __basic_any_access;
|
||||
|
||||
__basic_any() = default;
|
||||
|
||||
//! \brief Constructs a \c __basic_any<__ireference<_Interface>> from an lvalue
|
||||
//! reference to a \c __basic_any<_Interface>.
|
||||
_CCCL_HOST_DEVICE_API explicit __basic_any(
|
||||
::cuda::std::__maybe_const<__is_const_ref, __basic_any<interface_type>>& __other) noexcept
|
||||
{
|
||||
this->__set_ref(__other.__get_vptr(), __other.__get_optr());
|
||||
}
|
||||
|
||||
//! \brief Constructs a \c __basic_any<__ireference<_Interface>> from a
|
||||
//! vtable pointer and an object pointer.
|
||||
_CCCL_HOST_DEVICE_API
|
||||
__basic_any(__vptr_for<interface_type> __vptr, ::cuda::std::__maybe_const<__is_const_ref, void>* __optr) noexcept
|
||||
: __vptr_(__vptr)
|
||||
, __optr_(__optr)
|
||||
{}
|
||||
|
||||
//! \brief No-op.
|
||||
_CCCL_NODEBUG_API void reset() noexcept {}
|
||||
|
||||
//! \brief No-op.
|
||||
_CCCL_NODEBUG_API void __release_() noexcept {}
|
||||
|
||||
//! \brief Rebinds the reference with a vtable pointer and object pointer.
|
||||
_CCCL_HOST_DEVICE_API void
|
||||
__set_ref(__vptr_for<interface_type> __vptr, ::cuda::std::__maybe_const<__is_const_ref, void>* __obj) noexcept
|
||||
{
|
||||
__vptr_ = __vptr;
|
||||
__optr_ = __vptr_ ? __obj : nullptr;
|
||||
}
|
||||
|
||||
//! \brief Rebinds the reference with a vtable pointer for a different
|
||||
//! interface and object pointer. The vtable pointer is cast to the correct
|
||||
//! type. If the cast fails, the reference is set to null.
|
||||
template <class _VTable>
|
||||
_CCCL_HOST_DEVICE_API void
|
||||
__set_ref(_VTable const* __other, ::cuda::std::__maybe_const<__is_const_ref, void>* __obj) noexcept
|
||||
{
|
||||
using _OtherInterface = typename _VTable::interface;
|
||||
__vptr_ = __try_vptr_cast<_OtherInterface, interface_type>(__other);
|
||||
__optr_ = __vptr_ ? __obj : nullptr;
|
||||
}
|
||||
|
||||
//! \brief Rebinds the reference with a pointer to an __iset vtable, which
|
||||
//! is cast to a pointer to the vtable for `_Interface`. If \c _Interface
|
||||
//! is a specialization `__iset_<Is...>`, the cast succeeds if the
|
||||
//! \c Is... is a subset of `Interfaces...`. Otherwise, the cast succeeds
|
||||
//! if the \c _Interface is a base of one of `Interfaces...`.
|
||||
template <class... _Interfaces>
|
||||
_CCCL_HOST_DEVICE_API void
|
||||
__set_ref(__iset_vptr<_Interfaces...> __other, ::cuda::std::__maybe_const<__is_const_ref, void>* __obj) noexcept
|
||||
{
|
||||
using _OtherInterface = __iset_<_Interfaces...>;
|
||||
__vptr_ = __try_vptr_cast<_OtherInterface, interface_type>(__other);
|
||||
__optr_ = __vptr_ ? __obj : nullptr;
|
||||
}
|
||||
|
||||
template <class _SrcCvAny>
|
||||
_CCCL_HOST_DEVICE_API void __convert_from(_SrcCvAny&& __from)
|
||||
{
|
||||
using __src_interface_t _CCCL_NODEBUG_ALIAS = typename ::cuda::std::remove_reference_t<_SrcCvAny>::interface_type;
|
||||
if (!__from.has_value())
|
||||
{
|
||||
__throw_bad_any_cast();
|
||||
}
|
||||
auto __to_vptr = __vptr_cast<__src_interface_t, interface_type>(__from.__get_vptr());
|
||||
__set_ref(__to_vptr, __from.__get_optr());
|
||||
}
|
||||
|
||||
_CCCL_NODEBUG_API auto __get_optr() const noexcept -> ::cuda::std::__maybe_const<__is_const_ref, void>*
|
||||
{
|
||||
return __optr_;
|
||||
}
|
||||
|
||||
_CCCL_NODEBUG_API auto __get_vptr() const noexcept -> __vptr_for<interface_type>
|
||||
{
|
||||
return __vptr_;
|
||||
}
|
||||
|
||||
_CCCL_NODEBUG_API auto __get_rtti() const noexcept -> __rtti const*
|
||||
{
|
||||
return __vptr_->__query_interface(__iunknown());
|
||||
}
|
||||
|
||||
__vptr_for<interface_type> __vptr_{};
|
||||
::cuda::std::__maybe_const<__is_const_ref, void>* __optr_{};
|
||||
};
|
||||
|
||||
_CCCL_END_NV_DIAG_SUPPRESS()
|
||||
_CCCL_DIAG_POP
|
||||
|
||||
//!
|
||||
//! __basic_any<_Interface&>
|
||||
//!
|
||||
template <class _Interface>
|
||||
struct _CCCL_TYPE_VISIBILITY_DEFAULT __basic_any<_Interface&> : __basic_any<__ireference<_Interface>>
|
||||
{
|
||||
static_assert(::cuda::std::is_class_v<_Interface>, "expecting a class type");
|
||||
using typename __basic_any<__ireference<_Interface>>::interface_type;
|
||||
using __basic_any<__ireference<_Interface>>::__is_const_ref;
|
||||
|
||||
_CCCL_NODEBUG_API __basic_any(__basic_any&& __other) noexcept
|
||||
: __basic_any(const_cast<__basic_any const&>(__other))
|
||||
{}
|
||||
|
||||
_CCCL_NODEBUG_API __basic_any(__basic_any& __other) noexcept
|
||||
: __basic_any(const_cast<__basic_any const&>(__other))
|
||||
{}
|
||||
|
||||
_CCCL_HOST_DEVICE_API __basic_any(__basic_any const& __other) noexcept
|
||||
: __basic_any<__ireference<_Interface>>()
|
||||
{
|
||||
this->__set_ref(__other.__get_vptr(), __other.__get_optr());
|
||||
}
|
||||
|
||||
_CCCL_TEMPLATE(class _Tp, class _Up = ::cuda::std::remove_const_t<_Tp>)
|
||||
_CCCL_REQUIRES((!__is_basic_any<_Up>) _CCCL_AND(__is_const_ref || !::cuda::std::is_const_v<_Tp>)
|
||||
_CCCL_AND __satisfies<_Up, interface_type>)
|
||||
_CCCL_HOST_DEVICE_API __basic_any(_Tp& __obj) noexcept
|
||||
: __basic_any<__ireference<_Interface>>()
|
||||
{
|
||||
__vptr_for<interface_type> const __vptr = ::cuda::__get_vtable_ptr_for<interface_type, _Up>();
|
||||
this->__set_ref(__vptr, &__obj);
|
||||
}
|
||||
|
||||
_CCCL_TEMPLATE(class _SrcInterface)
|
||||
_CCCL_REQUIRES((!::cuda::std::same_as<_SrcInterface, _Interface&>) _CCCL_AND //
|
||||
(!__is_value_v<_SrcInterface>) _CCCL_AND //
|
||||
__any_convertible_to<__basic_any<_SrcInterface>, __basic_any>)
|
||||
_CCCL_HOST_DEVICE_API __basic_any(__basic_any<_SrcInterface>&& __src) noexcept
|
||||
: __basic_any<__ireference<_Interface>>()
|
||||
{
|
||||
this->__set_ref(__src.__get_vptr(), __src.__get_optr());
|
||||
}
|
||||
|
||||
_CCCL_TEMPLATE(class _SrcInterface)
|
||||
_CCCL_REQUIRES((!::cuda::std::same_as<_SrcInterface, _Interface&>) _CCCL_AND //
|
||||
__any_convertible_to<__basic_any<_SrcInterface>&, __basic_any>)
|
||||
_CCCL_HOST_DEVICE_API __basic_any(__basic_any<_SrcInterface>& __src) noexcept
|
||||
: __basic_any<__ireference<_Interface>>()
|
||||
{
|
||||
this->__set_ref(__src.__get_vptr(), __src.__get_optr());
|
||||
}
|
||||
|
||||
_CCCL_TEMPLATE(class _SrcInterface)
|
||||
_CCCL_REQUIRES((!::cuda::std::same_as<_SrcInterface, _Interface&>) _CCCL_AND //
|
||||
__any_convertible_to<__basic_any<_SrcInterface> const&, __basic_any>)
|
||||
_CCCL_HOST_DEVICE_API __basic_any(__basic_any<_SrcInterface> const& __src) noexcept
|
||||
: __basic_any<__ireference<_Interface>>()
|
||||
{
|
||||
this->__set_ref(__src.__get_vptr(), __src.__get_optr());
|
||||
}
|
||||
|
||||
auto operator=(__basic_any&&) -> __basic_any& = delete;
|
||||
auto operator=(__basic_any const&) -> __basic_any& = delete;
|
||||
|
||||
_CCCL_NODEBUG_API auto move() & noexcept -> __basic_any<__ireference<_Interface>>&&
|
||||
{
|
||||
return ::cuda::std::move(*this);
|
||||
}
|
||||
|
||||
private:
|
||||
template <class>
|
||||
friend struct __basic_any;
|
||||
friend struct __basic_any_access;
|
||||
|
||||
__basic_any() = default;
|
||||
};
|
||||
|
||||
_CCCL_END_NAMESPACE_CUDA
|
||||
|
||||
#include <cuda/std/__cccl/epilogue.h>
|
||||
|
||||
#endif // _CUDA___UTILITY_BASIC_ANY_BASIC_ANY_REF_H
|
||||
@@ -0,0 +1,589 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of libcu++, the C++ Standard Library for your entire system,
|
||||
// under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
// SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef _CUDA___UTILITY_BASIC_ANY_BASIC_ANY_VALUE_H
|
||||
#define _CUDA___UTILITY_BASIC_ANY_BASIC_ANY_VALUE_H
|
||||
|
||||
#include <cuda/std/detail/__config>
|
||||
|
||||
#if defined(_CCCL_IMPLICIT_SYSTEM_HEADER_GCC)
|
||||
# pragma GCC system_header
|
||||
#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_CLANG)
|
||||
# pragma clang system_header
|
||||
#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_MSVC)
|
||||
# pragma system_header
|
||||
#endif // no system header
|
||||
|
||||
#include <cuda/__utility/__basic_any/basic_any_base.h>
|
||||
#include <cuda/__utility/__basic_any/basic_any_fwd.h>
|
||||
#include <cuda/__utility/__basic_any/basic_any_ref.h>
|
||||
#include <cuda/__utility/__basic_any/conversions.h>
|
||||
#include <cuda/__utility/__basic_any/interfaces.h>
|
||||
#include <cuda/__utility/__basic_any/rtti.h>
|
||||
#include <cuda/__utility/__basic_any/semiregular.h>
|
||||
#include <cuda/__utility/__basic_any/storage.h>
|
||||
#include <cuda/__utility/__basic_any/virtual_tables.h>
|
||||
#include <cuda/std/__concepts/constructible.h>
|
||||
#include <cuda/std/__concepts/same_as.h>
|
||||
#include <cuda/std/__new/device_new.h>
|
||||
#include <cuda/std/__new/launder.h>
|
||||
#include <cuda/std/__type_traits/decay.h>
|
||||
#include <cuda/std/__type_traits/is_callable.h>
|
||||
#include <cuda/std/__type_traits/is_class.h>
|
||||
#include <cuda/std/__type_traits/is_const.h>
|
||||
#include <cuda/std/__type_traits/is_nothrow_constructible.h>
|
||||
#include <cuda/std/__type_traits/remove_reference.h>
|
||||
#include <cuda/std/__utility/in_place.h>
|
||||
#include <cuda/std/__utility/move.h>
|
||||
#include <cuda/std/__utility/swap.h>
|
||||
#include <cuda/std/__utility/typeid.h>
|
||||
#include <cuda/std/initializer_list>
|
||||
|
||||
#include <cuda/std/__cccl/prologue.h>
|
||||
|
||||
_CCCL_BEGIN_NAMESPACE_CUDA
|
||||
|
||||
//!
|
||||
//! __basic_any
|
||||
//!
|
||||
template <class _Interface>
|
||||
struct _CCCL_TYPE_VISIBILITY_DEFAULT __basic_any : __basic_any_base<_Interface>
|
||||
{
|
||||
private:
|
||||
static_assert(::cuda::std::is_class_v<_Interface>,
|
||||
"__basic_any requires an interface type, or a pointer or reference to an interface "
|
||||
"type.");
|
||||
static_assert(!::cuda::std::is_const_v<_Interface>, "__basic_any does not support const-qualified interfaces.");
|
||||
|
||||
static constexpr bool __movable = __extension_of<_Interface, __imovable<>>;
|
||||
static constexpr bool __copyable = __extension_of<_Interface, __icopyable<>>;
|
||||
|
||||
using __basic_any_base<_Interface>::__size_;
|
||||
using __basic_any_base<_Interface>::__align_;
|
||||
using __basic_any_base<_Interface>::__vptr_;
|
||||
using __basic_any_base<_Interface>::__buffer_;
|
||||
|
||||
public:
|
||||
using interface_type = _Interface;
|
||||
|
||||
//! @brief Constructs an empty `__basic_any` object.
|
||||
//! @post `has_value() == false`
|
||||
__basic_any() = default;
|
||||
|
||||
// NOLINTBEGIN(bugprone-forwarding-reference-overload)
|
||||
//! @brief Constructs a `__basic_any` object that contains a copy of `__value`.
|
||||
//! @pre `__value` must be move constructible. `_Tp` must satisfy the
|
||||
//! requirements of `_Interface`.
|
||||
//! @post `has_value() == true`
|
||||
_CCCL_TEMPLATE(class _Tp, class _Up = ::cuda::std::decay_t<_Tp>)
|
||||
_CCCL_REQUIRES((!__is_basic_any<_Up>)
|
||||
// The following constraint seems to trip up a lot of compilers, so leave it out.
|
||||
// _CCCL_AND ::cuda::std::constructible_from<_Up, _Tp>
|
||||
_CCCL_AND __satisfies<_Up, _Interface>)
|
||||
_CCCL_HOST_DEVICE_API __basic_any(_Tp&& __value) noexcept(
|
||||
__is_small<_Up, __movable>(__size_, __align_) && ::cuda::std::is_nothrow_constructible_v<_Up, _Tp>)
|
||||
{
|
||||
__emplace<_Up>(static_cast<_Tp&&>(__value));
|
||||
}
|
||||
// NOLINTEND(bugprone-forwarding-reference-overload)
|
||||
|
||||
//! @brief Constructs a `__basic_any` object that contains a new object of type `_Tp`
|
||||
//! constructed as `_Tp(__args...)`, or as `_Tp{__args...}` if `_Tp(__args...)` is
|
||||
//! ill-formed.
|
||||
//! @pre `_Tp` must satisfy the requirements of `_Interface`.
|
||||
//! @post `has_value() == true`
|
||||
_CCCL_TEMPLATE(class _Tp, class _Up = ::cuda::std::decay_t<_Tp>, class... _Args)
|
||||
_CCCL_REQUIRES(__initializable_from<_Up, _Args...> _CCCL_AND __satisfies<_Up, _Interface>)
|
||||
_CCCL_HOST_DEVICE_API explicit __basic_any(::cuda::std::in_place_type_t<_Tp>, _Args&&... __args) noexcept(
|
||||
__is_small<_Up, __movable>(__size_, __align_) && __nothrow_initializable_from<_Up, _Args...>)
|
||||
{
|
||||
__emplace<_Up>(static_cast<_Args&&>(__args)...);
|
||||
}
|
||||
|
||||
//! @brief Constructs a `__basic_any` object that contains a new object of type `_Tp`
|
||||
//! constructed as `_Tp(__il, __args...)`, or as `_Tp{__il, __args...}` if
|
||||
//! `_Tp(__il, __args...)` is ill-formed.
|
||||
//! @pre `_Tp` must satisfy the requirements of `_Interface`.
|
||||
//! @post `has_value() == true`
|
||||
_CCCL_TEMPLATE(class _Tp, class _Up, class _Vp = ::cuda::std::decay_t<_Tp>, class... _Args)
|
||||
_CCCL_REQUIRES(
|
||||
__initializable_from<_Vp, ::cuda::std::initializer_list<_Up>&, _Args...> _CCCL_AND __satisfies<_Up, _Interface>)
|
||||
_CCCL_HOST_DEVICE_API explicit __basic_any(
|
||||
::cuda::std::in_place_type_t<_Tp>,
|
||||
::cuda::std::initializer_list<_Up> __il,
|
||||
_Args&&... __args) noexcept(__is_small<_Vp, __movable>(__size_, __align_)
|
||||
&& __nothrow_initializable_from<_Vp, ::cuda::std::initializer_list<_Up>&, _Args...>)
|
||||
{
|
||||
__emplace<_Vp>(__il, static_cast<_Args&&>(__args)...);
|
||||
}
|
||||
|
||||
//! @brief Constructs a `__basic_any` object that contains a new object of type `_Tp`
|
||||
//! constructed as `_Tp(__fn(__args...))`.
|
||||
//! @pre `_Tp` must satisfy the requirements of `_Interface`.
|
||||
//! @post `has_value() == true`
|
||||
_CCCL_TEMPLATE(class _Tp, class _Up = ::cuda::std::decay_t<_Tp>, class _Fn, class... _Args)
|
||||
_CCCL_REQUIRES(__emplaceable_from<_Up, _Fn, _Args...> _CCCL_AND __satisfies<_Up, _Interface>)
|
||||
_CCCL_HOST_DEVICE_API explicit __basic_any(::cuda::in_place_from_type_t<_Tp>, _Fn&& __fn, _Args&&... __args) noexcept(
|
||||
__is_small<_Up, __movable>(__size_, __align_) && __nothrow_emplaceable_from<_Up, _Fn, _Args...>)
|
||||
{
|
||||
__emplace_from<_Up>(static_cast<_Fn&&>(__fn), static_cast<_Args&&>(__args)...);
|
||||
}
|
||||
|
||||
// We use base classes to implement movability and copyability. All we need here is to
|
||||
// accept the default implementations.
|
||||
__basic_any(__basic_any&& __other) = default;
|
||||
__basic_any(__basic_any const& __other) = default;
|
||||
|
||||
//! @brief Converting constructor that move constructs from a compatible
|
||||
//! `__basic_any` object.
|
||||
//! @pre Let `I` be the decayed type of `_OtherInterface`. `I` must extend
|
||||
//! `_Interface`. If `_OtherInterface` is a reference type, then `I` must
|
||||
//! extend `__icopyable<>`. Otherwise, `I` must extend `__imovable<>`.
|
||||
//! @post `__other.has_value() == false` and `has_value()` is `true` if and
|
||||
//! only if `__other.has_value()` was `true`.
|
||||
_CCCL_TEMPLATE(class _OtherInterface)
|
||||
_CCCL_REQUIRES((!::cuda::std::same_as<_OtherInterface&, _Interface&>)
|
||||
_CCCL_AND __any_convertible_to<__basic_any<_OtherInterface>, __basic_any>)
|
||||
_CCCL_HOST_DEVICE_API __basic_any(__basic_any<_OtherInterface>&& __other)
|
||||
{
|
||||
__convert_from(::cuda::std::move(__other));
|
||||
}
|
||||
|
||||
//! @brief Converting constructor that copy constructs from a compatible
|
||||
//! `__basic_any` object.
|
||||
//! @pre The decayed type of `_OtherInterface` must extend `_Interface` and
|
||||
//! `__icopyable<>`.
|
||||
//! @post `has_value() == __other.has_value()`.
|
||||
_CCCL_TEMPLATE(class _OtherInterface)
|
||||
_CCCL_REQUIRES((!::cuda::std::same_as<_OtherInterface&, _Interface&>)
|
||||
_CCCL_AND __any_convertible_to<__basic_any<_OtherInterface> const&, __basic_any>)
|
||||
_CCCL_HOST_DEVICE_API __basic_any(__basic_any<_OtherInterface> const& __other)
|
||||
{
|
||||
__convert_from(__other);
|
||||
}
|
||||
|
||||
//! @brief Non-template converting constructors from the corresponding
|
||||
//! reference type `__basic_any<_Interface&>`. These enable implicit
|
||||
//! conversion from proxy types (e.g. Cython's __Pyx_FakeReference)
|
||||
//! that wrap a `__basic_any<_Interface&>` and provide
|
||||
//! `operator __basic_any<_Interface&>&()`, since non-template parameters
|
||||
//! participate in implicit conversion sequences.
|
||||
//! @pre `_Interface` must extend `__icopyable<>` (converting a ref to
|
||||
//! a value requires copying the referenced object).
|
||||
template <bool _Copyable = __copyable, ::cuda::std::enable_if_t<_Copyable, int> = 0>
|
||||
_CCCL_HOST_DEVICE_API __basic_any(__basic_any<_Interface&> const& __other)
|
||||
{
|
||||
__convert_from(__other);
|
||||
}
|
||||
|
||||
template <bool _Copyable = __copyable, ::cuda::std::enable_if_t<_Copyable, int> = 0>
|
||||
_CCCL_HOST_DEVICE_API __basic_any(__basic_any<_Interface&>&& __other)
|
||||
{
|
||||
__convert_from(__other);
|
||||
}
|
||||
|
||||
#if _CCCL_COMPILER(CLANG, <, 12) || _CCCL_COMPILER(GCC, <, 11)
|
||||
// Older versions of clang and gcc need help disambiguating between
|
||||
// __basic_any<__ireference<I>> and __basic_any<I&>.
|
||||
_CCCL_TEMPLATE(class _OtherInterface)
|
||||
_CCCL_REQUIRES(__any_convertible_to<__basic_any<_OtherInterface&>, __basic_any>)
|
||||
_CCCL_HOST_DEVICE_API __basic_any(__basic_any<_OtherInterface&>&& __other)
|
||||
{
|
||||
__convert_from(__other);
|
||||
}
|
||||
|
||||
_CCCL_TEMPLATE(class _OtherInterface)
|
||||
_CCCL_REQUIRES(__any_convertible_to<__basic_any<_OtherInterface&>, __basic_any>)
|
||||
_CCCL_HOST_DEVICE_API __basic_any(__basic_any<_OtherInterface&> const& __other)
|
||||
{
|
||||
__convert_from(__other);
|
||||
}
|
||||
#endif // _CCCL_COMPILER(CLANG, <, 12) || _CCCL_COMPILER(GCC, <, 11)
|
||||
|
||||
//! @brief Destroys the contained value, if any.
|
||||
_CCCL_HOST_DEVICE_API ~__basic_any()
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
// We use base classes to implement movability and copyability. All we need here is to
|
||||
// accept the default implementations.
|
||||
auto operator=(__basic_any&& __other) -> __basic_any& = default;
|
||||
auto operator=(__basic_any const& __other) -> __basic_any& = default;
|
||||
|
||||
#if !_CCCL_CUDA_COMPILER(NVCC, <, 12, 9)
|
||||
//! @brief Converting move assignment operator from a compatible `__basic_any`
|
||||
//! object.
|
||||
//!
|
||||
//! Equivalent to:
|
||||
//!
|
||||
//! @code{.cpp}
|
||||
//! __basic_any(cuda::std::move(__other)).swap(*this);
|
||||
//! return *this;
|
||||
//! @endcode
|
||||
_CCCL_TEMPLATE(class _OtherInterface)
|
||||
_CCCL_REQUIRES((!::cuda::std::same_as<_OtherInterface, _Interface>)
|
||||
_CCCL_AND __any_convertible_to<__basic_any<_OtherInterface>, __basic_any>)
|
||||
_CCCL_HOST_DEVICE_API auto operator=(__basic_any<_OtherInterface>&& __other) -> __basic_any&
|
||||
{
|
||||
return __assign_from(::cuda::std::move(__other));
|
||||
}
|
||||
|
||||
//! @brief Converting copy assignment operator from a compatible `__basic_any`
|
||||
//! object.
|
||||
//!
|
||||
//! Equivalent to:
|
||||
//!
|
||||
//! @code{.cpp}
|
||||
//! __basic_any(__other).swap(*this);
|
||||
//! return *this;
|
||||
//! @endcode
|
||||
_CCCL_TEMPLATE(class _OtherInterface)
|
||||
_CCCL_REQUIRES((!::cuda::std::same_as<_OtherInterface, _Interface>)
|
||||
_CCCL_AND __any_convertible_to<__basic_any<_OtherInterface> const&, __basic_any>)
|
||||
_CCCL_HOST_DEVICE_API auto operator=(__basic_any<_OtherInterface> const& __other) -> __basic_any&
|
||||
{
|
||||
return __assign_from(__other);
|
||||
}
|
||||
#else
|
||||
// nvcc 12.0 has a bug with its concepts implementation where substitution occurs too
|
||||
// early here causing a hard error. So we use SFINAE to work around it.
|
||||
template <class _OtherInterface,
|
||||
::cuda::std::enable_if_t<!::cuda::std::same_as<_OtherInterface, _Interface>, int> = 0,
|
||||
::cuda::std::enable_if_t<__any_convertible_to<__basic_any<_OtherInterface>, __basic_any>, int> = 0>
|
||||
_CCCL_HOST_DEVICE_API auto operator=(__basic_any<_OtherInterface>&& __other) -> __basic_any&
|
||||
{
|
||||
return __assign_from(::cuda::std::move(__other));
|
||||
}
|
||||
|
||||
template <class _OtherInterface,
|
||||
::cuda::std::enable_if_t<!::cuda::std::same_as<_OtherInterface, _Interface>, int> = 0,
|
||||
::cuda::std::enable_if_t<__any_convertible_to<__basic_any<_OtherInterface> const&, __basic_any>, int> = 0>
|
||||
_CCCL_HOST_DEVICE_API auto operator=(__basic_any<_OtherInterface> const& __other) -> __basic_any&
|
||||
{
|
||||
return __assign_from(__other);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if _CCCL_COMPILER(CLANG, <, 12) || _CCCL_COMPILER(GCC, <, 11)
|
||||
// Older versions of clang and gcc need help disambiguating between
|
||||
// __basic_any<__ireference<I>> and __basic_any<I&>.
|
||||
_CCCL_TEMPLATE(class _OtherInterface)
|
||||
_CCCL_REQUIRES(__any_convertible_to<__basic_any<_OtherInterface&>, __basic_any>)
|
||||
_CCCL_HOST_DEVICE_API auto operator=(__basic_any<_OtherInterface&> __other) -> __basic_any&
|
||||
{
|
||||
return __assign_from(__other);
|
||||
}
|
||||
#endif // _CCCL_COMPILER(CLANG, <, 12) || _CCCL_COMPILER(GCC, <, 11)
|
||||
|
||||
//! @brief Implicitly convert to a `__basic_any` non-const reference type:
|
||||
[[nodiscard]] _CCCL_HOST_DEVICE_API operator __basic_any<__ireference<_Interface>>() & noexcept
|
||||
{
|
||||
return __basic_any<__ireference<_Interface>>(*this);
|
||||
}
|
||||
|
||||
//! @brief Implicitly convert to a `__basic_any` const reference type:
|
||||
[[nodiscard]] _CCCL_HOST_DEVICE_API operator __basic_any<__ireference<_Interface const>>() const& noexcept
|
||||
{
|
||||
return __basic_any<__ireference<_Interface const>>(*this);
|
||||
}
|
||||
|
||||
//! @brief Exchanges the values of two `__basic_any` objects.
|
||||
_CCCL_HOST_DEVICE_API void swap(__basic_any& __other) noexcept
|
||||
{
|
||||
//! if both objects refer to heap-allocated object, we can just
|
||||
//! swap the pointers. otherwise, do it the slow(er) way.
|
||||
if (!__in_situ() && !__other.__in_situ())
|
||||
{
|
||||
::cuda::std::swap(__vptr_, __other.__vptr_);
|
||||
__swap_ptr_ptr(__buffer_, __other.__buffer_);
|
||||
}
|
||||
|
||||
__basic_any __tmp;
|
||||
__tmp.__convert_from(::cuda::std::move(*this));
|
||||
(*this).__convert_from(::cuda::std::move(__other));
|
||||
__other.__convert_from(::cuda::std::move(__tmp));
|
||||
}
|
||||
|
||||
//! @brief Exchanges the values of two `__basic_any` objects.
|
||||
friend _CCCL_NODEBUG_API void swap(__basic_any& __lhs, __basic_any& __rhs) noexcept
|
||||
{
|
||||
__lhs.swap(__rhs);
|
||||
}
|
||||
|
||||
//! @brief Emplaces a new object of type `_Tp` constructed as `_Tp(__args...)`, or as
|
||||
//! `_Tp{__args...}` if `_Tp(__args...)` is ill-formed.
|
||||
//! @pre `_Tp` must satisfy the requirements of `_Interface`.
|
||||
//! @post `has_value() == true`
|
||||
_CCCL_TEMPLATE(class _Tp, class _Up = ::cuda::std::decay_t<_Tp>, class... _Args)
|
||||
_CCCL_REQUIRES(__initializable_from<_Up, _Args...>)
|
||||
_CCCL_HOST_DEVICE_API auto emplace(_Args&&... __args) noexcept(
|
||||
__is_small<_Up, __movable>(__size_, __align_) && __nothrow_initializable_from<_Up, _Args...>) -> _Up&
|
||||
{
|
||||
reset();
|
||||
return __emplace<_Up>(static_cast<_Args&&>(__args)...);
|
||||
}
|
||||
|
||||
//! @brief Emplaces a new object of type `_Tp` constructed as `_Tp(__il, __args...)`, or
|
||||
//! as `_Tp{__il, __args...}` if `_Tp(__il, __args...)` is ill-formed.
|
||||
//! @pre `_Tp` must satisfy the requirements of `_Interface`.
|
||||
//! @post `has_value() == true`
|
||||
_CCCL_TEMPLATE(class _Tp, class _Up, class _Vp = ::cuda::std::decay_t<_Tp>, class... _Args)
|
||||
_CCCL_REQUIRES(__initializable_from<_Vp, ::cuda::std::initializer_list<_Up>&, _Args...>)
|
||||
_CCCL_HOST_DEVICE_API auto emplace(::cuda::std::initializer_list<_Up> __il, _Args&&... __args) noexcept(
|
||||
__is_small<_Vp, __movable>(__size_, __align_)
|
||||
&& __nothrow_initializable_from<_Vp, ::cuda::std::initializer_list<_Up>&, _Args...>) -> _Vp&
|
||||
{
|
||||
reset();
|
||||
return __emplace<_Vp>(__il, static_cast<_Args&&>(__args)...);
|
||||
}
|
||||
|
||||
//! @brief Emplaces a new object of type `_Tp` constructed as
|
||||
//! `_Tp{__args...}`.
|
||||
//! @pre `_Tp` must satisfy the requirements of `_Interface`.
|
||||
//! @post `has_value() == true`
|
||||
_CCCL_TEMPLATE(class _Tp, class _Up = ::cuda::std::decay_t<_Tp>, class _Fn, class... _Args)
|
||||
_CCCL_REQUIRES(__emplaceable_from<_Up, _Fn, _Args...>)
|
||||
_CCCL_HOST_DEVICE_API auto emplace_from(_Fn&& __fn, _Args&&... __args) noexcept(
|
||||
__is_small<_Up, __movable>(__size_, __align_) && __nothrow_emplaceable_from<_Up, _Fn, _Args...>) -> _Up&
|
||||
{
|
||||
reset();
|
||||
return __emplace_from<_Up>(static_cast<_Fn&&>(__fn), static_cast<_Args&&>(__args)...);
|
||||
}
|
||||
|
||||
//! @brief Tests whether the `__basic_any` object contains a value.
|
||||
[[nodiscard]] _CCCL_HOST_DEVICE_API auto has_value() const noexcept -> bool
|
||||
{
|
||||
return __get_vptr() != nullptr;
|
||||
}
|
||||
|
||||
//! @brief Resets the `__basic_any` object to an empty state.
|
||||
//! @post `has_value() == false`
|
||||
_CCCL_HOST_DEVICE_API void reset() noexcept
|
||||
{
|
||||
if (auto __vptr = __get_vptr())
|
||||
{
|
||||
_CCCL_ASSERT(__vptr->__query_interface(__iunknown())->__cookie_ == 0xDEADBEEF,
|
||||
"query_interface returned a bad pointer to the __iunknown vtable");
|
||||
__vptr->__query_interface(__iunknown())->__dtor_(__buffer_, __in_situ());
|
||||
__release_();
|
||||
}
|
||||
}
|
||||
|
||||
//! @brief Returns a reference to a type_info object representing the type of
|
||||
//! the contained object.
|
||||
[[nodiscard]] _CCCL_HOST_DEVICE_API auto type() const noexcept -> ::cuda::std::__type_info_ref
|
||||
{
|
||||
if (auto __vptr = __get_vptr())
|
||||
{
|
||||
_CCCL_ASSERT(__vptr->__query_interface(__iunknown())->__cookie_ == 0xDEADBEEF,
|
||||
"query_interface returned a bad pointer to the __iunknown vtable");
|
||||
return *__vptr->__query_interface(__iunknown())->__object_info_->__object_typeid_;
|
||||
}
|
||||
return _CCCL_TYPEID(void);
|
||||
}
|
||||
|
||||
//! @brief Returns a reference to a type_info object representing the type of
|
||||
//! the dynamic interface.
|
||||
//!
|
||||
//! The dynamic interface is the interface that was used to construct the
|
||||
//! object, which may be different from the current object's interface if
|
||||
//! there was a conversion.
|
||||
[[nodiscard]] _CCCL_HOST_DEVICE_API auto interface() const noexcept -> ::cuda::std::__type_info_ref
|
||||
{
|
||||
if (auto __vptr = __get_vptr())
|
||||
{
|
||||
_CCCL_ASSERT(__vptr->__query_interface(__iunknown())->__cookie_ == 0xDEADBEEF,
|
||||
"query_interface returned a bad pointer to the __iunknown vtable");
|
||||
return *__vptr->__query_interface(__iunknown())->__interface_typeid_;
|
||||
}
|
||||
return _CCCL_TYPEID(_Interface);
|
||||
}
|
||||
|
||||
#if !defined(_CCCL_DOXYGEN_INVOKED) // Do not document
|
||||
[[nodiscard]] _CCCL_HOST_DEVICE_API auto __in_situ() const noexcept -> bool
|
||||
{
|
||||
return __vptr_.__flag();
|
||||
}
|
||||
#endif // _CCCL_DOXYGEN_INVOKED
|
||||
|
||||
private:
|
||||
template <class>
|
||||
friend struct __basic_any;
|
||||
friend struct __basic_any_access;
|
||||
template <class, int>
|
||||
friend struct __basic_any_base;
|
||||
|
||||
_CCCL_HOST_DEVICE_API void __release_()
|
||||
{
|
||||
__vptr_for<_Interface> __vptr = nullptr;
|
||||
__vptr_.__set(__vptr, false);
|
||||
}
|
||||
|
||||
_CCCL_EXEC_CHECK_DISABLE
|
||||
template <class _Tp, class... _Args>
|
||||
_CCCL_HOST_DEVICE_API auto __emplace(_Args&&... __args) noexcept(
|
||||
__is_small<_Tp, __movable>(__size_, __align_) && __nothrow_initializable_from<_Tp, _Args...>) -> _Tp&
|
||||
{
|
||||
using __pointer_t = _Tp*;
|
||||
if constexpr (__is_small<_Tp, __movable>(__size_, __align_))
|
||||
{
|
||||
// in-place construction
|
||||
if constexpr (::cuda::std::constructible_from<_Tp, _Args...>)
|
||||
{
|
||||
// Prefer direct non-list initialization if possible.
|
||||
::new (__buffer_) _Tp(static_cast<_Args&&>(__args)...);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Otherwise, fall back to direct list initialization.
|
||||
::new (__buffer_) _Tp{static_cast<_Args&&>(__args)...};
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// heap allocation
|
||||
if constexpr (::cuda::std::constructible_from<_Tp, _Args...>)
|
||||
{
|
||||
// Prefer direct non-list initialization if possible.
|
||||
::new (__buffer_) __pointer_t{new _Tp(static_cast<_Args&&>(__args)...)};
|
||||
}
|
||||
else
|
||||
{
|
||||
// Otherwise, fall back to direct list initialization.
|
||||
::new (__buffer_) __pointer_t{new _Tp{static_cast<_Args&&>(__args)...}};
|
||||
}
|
||||
}
|
||||
|
||||
__vptr_for<_Interface> __vptr = ::cuda::__get_vtable_ptr_for<_Interface, _Tp>();
|
||||
__vptr_.__set(__vptr, __is_small<_Tp, __movable>(__size_, __align_));
|
||||
return *::cuda::std::launder(static_cast<_Tp*>(__get_optr()));
|
||||
}
|
||||
|
||||
_CCCL_EXEC_CHECK_DISABLE
|
||||
template <class _Tp, class _Fn, class... _Args>
|
||||
_CCCL_HOST_DEVICE_API auto __emplace_from(_Fn&& __fn, _Args&&... __args) noexcept(
|
||||
__is_small<_Tp, __movable>(__size_, __align_) && __nothrow_emplaceable_from<_Tp, _Fn, _Args...>) -> _Tp&
|
||||
{
|
||||
using __pointer_t = _Tp*;
|
||||
if constexpr (__is_small<_Tp, __movable>(__size_, __align_))
|
||||
{
|
||||
// in-place construction
|
||||
::new (__buffer_) _Tp(static_cast<_Fn&&>(__fn)(static_cast<_Args&&>(__args)...));
|
||||
}
|
||||
else
|
||||
{
|
||||
// heap allocation
|
||||
::new (__buffer_) __pointer_t{new _Tp(static_cast<_Fn&&>(__fn)(static_cast<_Args&&>(__args)...))};
|
||||
}
|
||||
|
||||
__vptr_for<_Interface> __vptr = ::cuda::__get_vtable_ptr_for<_Interface, _Tp>();
|
||||
__vptr_.__set(__vptr, __is_small<_Tp, __movable>(__size_, __align_));
|
||||
return *::cuda::std::launder(static_cast<_Tp*>(__get_optr()));
|
||||
}
|
||||
|
||||
// this overload handles moving from __basic_any<_SrcInterface> and
|
||||
// __basic_any<__ireference<_SrcInterface>> (but not
|
||||
// __basic_any<__ireference<_SrcInterface const>>).
|
||||
_CCCL_TEMPLATE(class _SrcInterface)
|
||||
_CCCL_REQUIRES(__any_castable_to<__basic_any<_SrcInterface>, __basic_any>)
|
||||
_CCCL_HOST_DEVICE_API void
|
||||
__convert_from(__basic_any<_SrcInterface>&& __from) noexcept(::cuda::std::same_as<_SrcInterface, _Interface>)
|
||||
{
|
||||
_CCCL_ASSERT(!has_value(), "forgot to clear the destination object first");
|
||||
using __src_interface_t _CCCL_NODEBUG_ALIAS = __remove_ireference_t<_SrcInterface>;
|
||||
// if the source is an lvalue reference, we need to copy from it.
|
||||
if constexpr (__is_lvalue_reference_v<_SrcInterface>)
|
||||
{
|
||||
__convert_from(__from); // will copy from the source
|
||||
}
|
||||
else if (auto __to_vptr = __vptr_cast<__src_interface_t, _Interface>(__from.__get_vptr()))
|
||||
{
|
||||
if (!__from.__in_situ())
|
||||
{
|
||||
using __void_ptr_t = void*;
|
||||
::new (__buffer_) __void_ptr_t(__from.__get_optr());
|
||||
__vptr_.__set(__to_vptr, false);
|
||||
__from.__release_();
|
||||
}
|
||||
else if constexpr (::cuda::std::same_as<_SrcInterface, _Interface>)
|
||||
{
|
||||
__from.__move_to(__buffer_);
|
||||
__vptr_.__set(__from.__get_vptr(), true);
|
||||
__from.reset();
|
||||
}
|
||||
else
|
||||
{
|
||||
bool const __small = __from.__move_to(__buffer_, __size_, __align_);
|
||||
__vptr_.__set(__to_vptr, __small);
|
||||
__from.reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// this overload handles copying from __basic_any<_Interface>,
|
||||
// __basic_any<__ireference<_Interface>>, and __basic_any<_Interface&>.
|
||||
_CCCL_TEMPLATE(class _SrcInterface)
|
||||
_CCCL_REQUIRES(__any_castable_to<__basic_any<_SrcInterface> const&, __basic_any>)
|
||||
_CCCL_HOST_DEVICE_API void __convert_from(__basic_any<_SrcInterface> const& __from)
|
||||
{
|
||||
_CCCL_ASSERT(!has_value(), "forgot to clear the destination object first");
|
||||
using __src_interface_t _CCCL_NODEBUG_ALIAS = __remove_ireference_t<::cuda::std::remove_reference_t<_SrcInterface>>;
|
||||
if (auto __to_vptr = __vptr_cast<__src_interface_t, _Interface>(__from.__get_vptr()))
|
||||
{
|
||||
bool const __small = __from.__copy_to(__buffer_, __size_, __align_);
|
||||
__vptr_.__set(__to_vptr, __small);
|
||||
}
|
||||
}
|
||||
|
||||
// Assignment from a compatible __basic_any object handled here:
|
||||
_CCCL_TEMPLATE(class _SrcCvAny)
|
||||
_CCCL_REQUIRES(__any_castable_to<_SrcCvAny, __basic_any>)
|
||||
_CCCL_HOST_DEVICE_API auto __assign_from(_SrcCvAny&& __src) -> __basic_any&
|
||||
{
|
||||
if (!__ptr_eq(this, &__src))
|
||||
{
|
||||
reset();
|
||||
__convert_from(static_cast<_SrcCvAny&&>(__src));
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
[[nodiscard]] _CCCL_HOST_DEVICE_API auto __get_vptr() const noexcept -> __vptr_for<_Interface>
|
||||
{
|
||||
return __vptr_.__get();
|
||||
}
|
||||
|
||||
[[nodiscard]] _CCCL_HOST_DEVICE_API auto __get_optr() noexcept -> void*
|
||||
{
|
||||
void* __pv = __buffer_;
|
||||
return __in_situ() ? __pv : *static_cast<void**>(__pv);
|
||||
}
|
||||
|
||||
_CCCL_DIAG_PUSH
|
||||
_CCCL_DIAG_SUPPRESS_MSVC(4702) // warning C4702: unreachable code (srsly where, msvc?)
|
||||
[[nodiscard]] _CCCL_HOST_DEVICE_API auto __get_optr() const noexcept -> void const*
|
||||
{
|
||||
void const* __pv = __buffer_;
|
||||
return __in_situ() ? __pv : *static_cast<void const* const*>(__pv);
|
||||
}
|
||||
_CCCL_DIAG_POP
|
||||
|
||||
[[nodiscard]] _CCCL_HOST_DEVICE_API auto __get_rtti() const noexcept -> __rtti const*
|
||||
{
|
||||
return __get_vptr()->__query_interface(__iunknown());
|
||||
}
|
||||
};
|
||||
|
||||
_CCCL_END_NAMESPACE_CUDA
|
||||
|
||||
#include <cuda/std/__cccl/epilogue.h>
|
||||
|
||||
#endif // _CUDA___UTILITY_BASIC_ANY_BASIC_ANY_VALUE_H
|
||||
@@ -0,0 +1,170 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of libcu++, the C++ Standard Library for your entire system,
|
||||
// under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
// SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef _CUDA___UTILITY_BASIC_ANY_CONVERSIONS_H
|
||||
#define _CUDA___UTILITY_BASIC_ANY_CONVERSIONS_H
|
||||
|
||||
#include <cuda/std/detail/__config>
|
||||
|
||||
#if defined(_CCCL_IMPLICIT_SYSTEM_HEADER_GCC)
|
||||
# pragma GCC system_header
|
||||
#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_CLANG)
|
||||
# pragma clang system_header
|
||||
#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_MSVC)
|
||||
# pragma system_header
|
||||
#endif // no system header
|
||||
|
||||
#include <cuda/__utility/__basic_any/basic_any_fwd.h>
|
||||
#include <cuda/__utility/__basic_any/interfaces.h>
|
||||
#include <cuda/std/__concepts/convertible_to.h>
|
||||
#include <cuda/std/__type_traits/add_pointer.h>
|
||||
#include <cuda/std/__type_traits/is_convertible.h>
|
||||
#include <cuda/std/__type_traits/remove_reference.h>
|
||||
#include <cuda/std/__type_traits/type_list.h>
|
||||
#include <cuda/std/__utility/declval.h>
|
||||
|
||||
#include <cuda/std/__cccl/prologue.h>
|
||||
|
||||
_CCCL_BEGIN_NAMESPACE_CUDA
|
||||
|
||||
//!
|
||||
//! conversions
|
||||
//!
|
||||
//! Can one __basic_any type convert to another? Implicitly? Explicitly?
|
||||
//! Statically? Dynamically? We answer these questions by mapping two
|
||||
//! cvref qualified __basic_any types to archetype types, and then using
|
||||
//! the built-in language rules to determine if the conversion is valid.
|
||||
//!
|
||||
template <bool _Movable, bool _Copyable>
|
||||
struct __archetype;
|
||||
|
||||
// Archetype for interfaces that extend neither __imovable nor __icopyable
|
||||
template <>
|
||||
struct __archetype<false, false> // immovable archetype
|
||||
{
|
||||
__archetype() = default;
|
||||
__archetype(__archetype&&) = delete;
|
||||
__archetype(const __archetype&) = delete;
|
||||
|
||||
template <class _Value>
|
||||
_CCCL_HOST_DEVICE_API __archetype(_Value) noexcept;
|
||||
template <class _Value>
|
||||
_CCCL_HOST_DEVICE_API __archetype(_Value*) = delete;
|
||||
};
|
||||
|
||||
// Archetype for interfaces that extend __imovable but not __icopyable
|
||||
template <>
|
||||
struct __archetype<true, false> : __archetype<false, false> // movable archetype
|
||||
{
|
||||
__archetype() = default;
|
||||
_CCCL_HOST_DEVICE_API __archetype(__archetype&&) noexcept;
|
||||
__archetype(const __archetype&) = delete;
|
||||
};
|
||||
|
||||
// Archetype for interfaces that extend __icopyable
|
||||
template <>
|
||||
struct __archetype<true, true> : __archetype<true, false>
|
||||
{
|
||||
__archetype() = default;
|
||||
_CCCL_HOST_DEVICE_API __archetype(__archetype const&);
|
||||
};
|
||||
|
||||
template <class _Interface>
|
||||
using __archetype_t _CCCL_NODEBUG_ALIAS =
|
||||
__archetype<__extension_of<_Interface, __imovable<>>, __extension_of<_Interface, __icopyable<>>>;
|
||||
|
||||
// Strip top-level cv- and ref-qualifiers from pointer types:
|
||||
template <class _Ty>
|
||||
_CCCL_HOST_DEVICE_API auto __normalize_interface(_Ty&&) -> _Ty;
|
||||
|
||||
template <class _Ty>
|
||||
_CCCL_HOST_DEVICE_API auto __normalize_interface(_Ty*) -> _Ty*;
|
||||
|
||||
template <class _Ty>
|
||||
using __normalize_t _CCCL_NODEBUG_ALIAS = decltype(::cuda::__normalize_interface(::cuda::std::declval<_Ty>()));
|
||||
|
||||
// Used to map a __basic_any specialization to a normalized interface type:
|
||||
template <class _Ty>
|
||||
extern ::cuda::std::__undefined<_Ty> __interface_from;
|
||||
template <class _Interface>
|
||||
extern _Interface __interface_from<__basic_any<_Interface>>;
|
||||
template <class _Interface>
|
||||
extern _Interface __interface_from<__basic_any<__ireference<_Interface>>>;
|
||||
template <class _Interface>
|
||||
extern _Interface& __interface_from<__basic_any<_Interface>&>;
|
||||
template <class _Interface>
|
||||
extern _Interface const& __interface_from<__basic_any<_Interface> const&>;
|
||||
template <class _Interface>
|
||||
extern ::cuda::std::add_pointer_t<_Interface> __interface_from<__basic_any<_Interface>*>;
|
||||
template <class _Interface>
|
||||
extern ::cuda::std::add_pointer_t<_Interface const> __interface_from<__basic_any<_Interface> const*>;
|
||||
template <class _Interface>
|
||||
extern ::cuda::std::add_pointer_t<_Interface> __interface_from<__basic_any<__ireference<_Interface>>*>;
|
||||
template <class _Interface>
|
||||
extern ::cuda::std::add_pointer_t<_Interface const> __interface_from<__basic_any<__ireference<_Interface>> const*>;
|
||||
|
||||
// Used to map a normalized interface type to an archetype for conversion testing:
|
||||
template <class _Interface>
|
||||
extern __archetype_t<_Interface> __as_archetype;
|
||||
template <class _Interface>
|
||||
extern __archetype_t<_Interface>& __as_archetype<_Interface&>;
|
||||
template <class _Interface>
|
||||
extern __archetype_t<_Interface> const& __as_archetype<_Interface const&>;
|
||||
template <class _Interface>
|
||||
extern __archetype_t<_Interface>* __as_archetype<_Interface*>;
|
||||
template <class _Interface>
|
||||
extern __archetype_t<_Interface> const* __as_archetype<_Interface const*>;
|
||||
template <class _Interface>
|
||||
extern __archetype_t<_Interface>& __as_archetype<__ireference<_Interface>>;
|
||||
template <class _Interface>
|
||||
extern __archetype_t<_Interface> const& __as_archetype<__ireference<_Interface const>>;
|
||||
|
||||
// Used to map an archetype to an immovable archetype
|
||||
template <class _Archetype>
|
||||
extern __archetype<false, false> __as_immovable;
|
||||
template <class _Archetype>
|
||||
extern __archetype<false, false>& __as_immovable<_Archetype&>;
|
||||
template <class _Archetype>
|
||||
extern __archetype<false, false> const& __as_immovable<_Archetype const&>;
|
||||
template <class _Archetype>
|
||||
extern __archetype<false, false>* __as_immovable<_Archetype*>;
|
||||
template <class _Archetype>
|
||||
extern __archetype<false, false> const* __as_immovable<_Archetype const*>;
|
||||
|
||||
template <class _CvAny>
|
||||
using __normalized_interface_of _CCCL_NODEBUG_ALIAS = __normalize_t<decltype(__interface_from<__normalize_t<_CvAny>>)>;
|
||||
|
||||
template <class _CvAny>
|
||||
using __src_archetype_of _CCCL_NODEBUG_ALIAS = decltype(__as_archetype<__normalized_interface_of<_CvAny>>);
|
||||
|
||||
template <class _CvAny>
|
||||
using __dst_archetype_of _CCCL_NODEBUG_ALIAS = decltype(__as_immovable<__src_archetype_of<_CvAny>>);
|
||||
|
||||
// If the archetypes are implicitly convertible, then it is possible to
|
||||
// dynamically cast from the source to the destination. The cast may fail,
|
||||
// but at least it is possible.
|
||||
template <class _SrcCvAny, class _DstCvAny>
|
||||
_CCCL_CONCEPT __any_castable_to =
|
||||
::cuda::std::convertible_to<__src_archetype_of<_SrcCvAny>, __dst_archetype_of<_DstCvAny>>;
|
||||
|
||||
// If the archetypes are implicitly convertible **and** the source interface
|
||||
// is an extension of the destination one, then it is possible to implicitly
|
||||
// convert from the source to the destination.
|
||||
template <class _SrcCvAny, class _DstCvAny>
|
||||
_CCCL_CONCEPT __any_convertible_to =
|
||||
__any_castable_to<_SrcCvAny, _DstCvAny> && //
|
||||
__extension_of<typename ::cuda::std::remove_reference_t<_SrcCvAny>::interface_type,
|
||||
typename ::cuda::std::remove_reference_t<_DstCvAny>::interface_type>;
|
||||
|
||||
_CCCL_END_NAMESPACE_CUDA
|
||||
|
||||
#include <cuda/std/__cccl/epilogue.h>
|
||||
|
||||
#endif // _CUDA___UTILITY_BASIC_ANY_CONVERSIONS_H
|
||||
@@ -0,0 +1,152 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of libcu++, the C++ Standard Library for your entire system,
|
||||
// under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
// SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef _CUDA___UTILITY_BASIC_ANY_DYNAMIC_ANY_CAST_H
|
||||
#define _CUDA___UTILITY_BASIC_ANY_DYNAMIC_ANY_CAST_H
|
||||
|
||||
#include <cuda/std/detail/__config>
|
||||
|
||||
#if defined(_CCCL_IMPLICIT_SYSTEM_HEADER_GCC)
|
||||
# pragma GCC system_header
|
||||
#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_CLANG)
|
||||
# pragma clang system_header
|
||||
#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_MSVC)
|
||||
# pragma system_header
|
||||
#endif // no system header
|
||||
|
||||
#include <cuda/__utility/__basic_any/access.h>
|
||||
#include <cuda/__utility/__basic_any/basic_any_fwd.h>
|
||||
#include <cuda/__utility/__basic_any/conversions.h>
|
||||
#include <cuda/std/__concepts/concept_macros.h>
|
||||
#include <cuda/std/__type_traits/is_pointer.h>
|
||||
#include <cuda/std/__utility/move.h>
|
||||
|
||||
#include <cuda/std/__cccl/prologue.h>
|
||||
|
||||
_CCCL_BEGIN_NAMESPACE_CUDA
|
||||
|
||||
//! \brief Casts one __basic_any reference type to another __basic_any type using
|
||||
//! runtime information to determine the validity of the conversion.
|
||||
//!
|
||||
//! \throws __bad_any_cast when \c __src cannot be dynamically cast to a
|
||||
//! \c __basic_any<_DstInterface>.
|
||||
_CCCL_TEMPLATE(class _DstInterface, class _SrcInterface)
|
||||
_CCCL_REQUIRES(__any_castable_to<__basic_any<_SrcInterface>, __basic_any<_DstInterface>>)
|
||||
[[nodiscard]] _CCCL_HOST_DEVICE_API auto __dynamic_any_cast(__basic_any<_SrcInterface>&& __src)
|
||||
-> __basic_any<_DstInterface>
|
||||
{
|
||||
auto __dst = __basic_any_access::__make<_DstInterface>();
|
||||
__basic_any_access::__cast_to(::cuda::std::move(__src), __dst);
|
||||
return __dst;
|
||||
}
|
||||
|
||||
//! \overload
|
||||
_CCCL_TEMPLATE(class _DstInterface, class _SrcInterface)
|
||||
_CCCL_REQUIRES(__any_castable_to<__basic_any<_SrcInterface>&, __basic_any<_DstInterface>>)
|
||||
[[nodiscard]] _CCCL_HOST_DEVICE_API auto __dynamic_any_cast(__basic_any<_SrcInterface>& __src)
|
||||
-> __basic_any<_DstInterface>
|
||||
{
|
||||
auto __dst = __basic_any_access::__make<_DstInterface>();
|
||||
__basic_any_access::__cast_to(__src, __dst);
|
||||
return __dst;
|
||||
}
|
||||
|
||||
//! \overload
|
||||
_CCCL_TEMPLATE(class _DstInterface, class _SrcInterface)
|
||||
_CCCL_REQUIRES(__any_castable_to<__basic_any<_SrcInterface> const&, __basic_any<_DstInterface>>)
|
||||
[[nodiscard]] _CCCL_HOST_DEVICE_API auto __dynamic_any_cast(__basic_any<_SrcInterface> const& __src)
|
||||
-> __basic_any<_DstInterface>
|
||||
{
|
||||
auto __dst = __basic_any_access::__make<_DstInterface>();
|
||||
__basic_any_access::__cast_to(__src, __dst);
|
||||
return __dst;
|
||||
}
|
||||
|
||||
//! \brief Casts a `__basic_any<_SrcInterface>*` into a `__basic_any<_DstInterface>`
|
||||
//! using runtime information to determine the validity of the conversion.
|
||||
//!
|
||||
//! \pre \c _DstInterface must be a pointer type.
|
||||
//!
|
||||
//! \returns \c nullptr when \c __src cannot be dynamically cast to a
|
||||
//! \c __basic_any<_DstInterface>.
|
||||
_CCCL_TEMPLATE(class _DstInterface, class _SrcInterface)
|
||||
_CCCL_REQUIRES(__any_castable_to<__basic_any<_SrcInterface>*, __basic_any<_DstInterface>>)
|
||||
[[nodiscard]] _CCCL_HOST_DEVICE_API auto __dynamic_any_cast(__basic_any<_SrcInterface>* __src)
|
||||
-> __basic_any<_DstInterface>
|
||||
{
|
||||
static_assert(
|
||||
::cuda::std::is_pointer_v<_DstInterface>,
|
||||
"when __dynamic_any_cast-ing from a pointer to a __basic_any, the destination type must be a pointer to an "
|
||||
"interface type.");
|
||||
auto __dst = __basic_any_access::__make<_DstInterface>();
|
||||
__basic_any_access::__cast_to(__src, __dst);
|
||||
return __dst;
|
||||
}
|
||||
|
||||
//! \overload
|
||||
_CCCL_TEMPLATE(class _DstInterface, class _SrcInterface)
|
||||
_CCCL_REQUIRES(__any_castable_to<__basic_any<_SrcInterface> const*, __basic_any<_DstInterface>>)
|
||||
[[nodiscard]] _CCCL_HOST_DEVICE_API auto __dynamic_any_cast(__basic_any<_SrcInterface> const* __src)
|
||||
-> __basic_any<_DstInterface>
|
||||
{
|
||||
static_assert(
|
||||
::cuda::std::is_pointer_v<_DstInterface>,
|
||||
"when __dynamic_any_cast-ing from a pointer to a __basic_any, the destination type must be a pointer to an "
|
||||
"interface type.");
|
||||
auto __dst = __basic_any_access::__make<_DstInterface>();
|
||||
__basic_any_access::__cast_to(__src, __dst);
|
||||
return __dst;
|
||||
}
|
||||
|
||||
#if _CCCL_COMPILER(GCC, <, 11)
|
||||
// Older versions of GCC have trouble deducing __basic_any<T&> from a type derived from
|
||||
// it, because __basic_any<T&> itself inherits from __basic_any<__ireference<T>>. GCC
|
||||
// cannot choose between the two base classes when deducing from a derived class.
|
||||
_CCCL_TEMPLATE(class _DstInterface, class _SrcAny)
|
||||
_CCCL_REQUIRES(__any_castable_to<typename _SrcAny::__basic_any, __basic_any<_DstInterface>>)
|
||||
[[nodiscard]] _CCCL_TRIVIAL_API auto __dynamic_any_cast(_SrcAny&& __src) -> __basic_any<_DstInterface>
|
||||
{
|
||||
return ::cuda::__dynamic_any_cast<_DstInterface>(static_cast<typename _SrcAny::__basic_any&&>(__src));
|
||||
}
|
||||
|
||||
_CCCL_TEMPLATE(class _DstInterface, class _SrcAny)
|
||||
_CCCL_REQUIRES(__any_castable_to<typename _SrcAny::__basic_any&, __basic_any<_DstInterface>>)
|
||||
[[nodiscard]] _CCCL_TRIVIAL_API auto __dynamic_any_cast(_SrcAny& __src) -> __basic_any<_DstInterface>
|
||||
{
|
||||
return ::cuda::__dynamic_any_cast<_DstInterface>(static_cast<typename _SrcAny::__basic_any&>(__src));
|
||||
}
|
||||
|
||||
_CCCL_TEMPLATE(class _DstInterface, class _SrcAny)
|
||||
_CCCL_REQUIRES(__any_castable_to<typename _SrcAny::__basic_any const&, __basic_any<_DstInterface>>)
|
||||
[[nodiscard]] _CCCL_TRIVIAL_API auto __dynamic_any_cast(_SrcAny const& __src) -> __basic_any<_DstInterface>
|
||||
{
|
||||
return ::cuda::__dynamic_any_cast<_DstInterface>(static_cast<typename _SrcAny::__basic_any const&>(__src));
|
||||
}
|
||||
|
||||
_CCCL_TEMPLATE(class _DstInterface, class _SrcAny)
|
||||
_CCCL_REQUIRES(__any_castable_to<typename _SrcAny::__basic_any*, __basic_any<_DstInterface>>)
|
||||
[[nodiscard]] _CCCL_TRIVIAL_API auto __dynamic_any_cast(_SrcAny* __src) -> __basic_any<_DstInterface>
|
||||
{
|
||||
return ::cuda::__dynamic_any_cast<_DstInterface>(static_cast<typename _SrcAny::__basic_any*>(__src));
|
||||
}
|
||||
|
||||
_CCCL_TEMPLATE(class _DstInterface, class _SrcAny)
|
||||
_CCCL_REQUIRES(__any_castable_to<typename _SrcAny::__basic_any const*, __basic_any<_DstInterface>>)
|
||||
[[nodiscard]] _CCCL_TRIVIAL_API auto __dynamic_any_cast(_SrcAny const* __src) -> __basic_any<_DstInterface>
|
||||
{
|
||||
return ::cuda::__dynamic_any_cast<_DstInterface>(static_cast<typename _SrcAny::__basic_any const*>(__src));
|
||||
}
|
||||
#endif
|
||||
|
||||
_CCCL_END_NAMESPACE_CUDA
|
||||
|
||||
#include <cuda/std/__cccl/epilogue.h>
|
||||
|
||||
#endif // _CUDA___UTILITY_BASIC_ANY_DYNAMIC_ANY_CAST_H
|
||||
@@ -0,0 +1,359 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of libcu++, the C++ Standard Library for your entire system,
|
||||
// under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
// SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef _CUDA___UTILITY_BASIC_ANY_INTERFACES_H
|
||||
#define _CUDA___UTILITY_BASIC_ANY_INTERFACES_H
|
||||
|
||||
#include <cuda/std/detail/__config>
|
||||
|
||||
#if defined(_CCCL_IMPLICIT_SYSTEM_HEADER_GCC)
|
||||
# pragma GCC system_header
|
||||
#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_CLANG)
|
||||
# pragma clang system_header
|
||||
#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_MSVC)
|
||||
# pragma system_header
|
||||
#endif // no system header
|
||||
|
||||
#include <cuda/__utility/__basic_any/basic_any_fwd.h>
|
||||
#include <cuda/__utility/__basic_any/overrides.h>
|
||||
#include <cuda/__utility/inherit.h>
|
||||
#include <cuda/std/__algorithm/find.h>
|
||||
#include <cuda/std/__algorithm/max.h>
|
||||
#include <cuda/std/__concepts/concept_macros.h>
|
||||
#include <cuda/std/__type_traits/is_callable.h>
|
||||
#include <cuda/std/__type_traits/is_class.h>
|
||||
#include <cuda/std/__type_traits/is_const.h>
|
||||
#include <cuda/std/__type_traits/remove_const.h>
|
||||
#include <cuda/std/__type_traits/type_set.h>
|
||||
|
||||
#include <cuda/std/__cccl/prologue.h>
|
||||
|
||||
_CCCL_BEGIN_NAMESPACE_CUDA
|
||||
|
||||
//!
|
||||
//! Interface type traits
|
||||
//!
|
||||
// The primary __remove_ireference_v template is defined in basic_any_fwd.cuh.
|
||||
template <class _Interface>
|
||||
extern _Interface __remove_ireference_v<_Interface const>;
|
||||
|
||||
template <class _Interface>
|
||||
extern _Interface __remove_ireference_v<__ireference<_Interface>>;
|
||||
|
||||
template <class _Interface>
|
||||
extern _Interface __remove_ireference_v<__ireference<_Interface const>>;
|
||||
|
||||
template <class _Interface>
|
||||
inline constexpr bool __is_value_v = ::cuda::std::is_class_v<_Interface>;
|
||||
|
||||
template <class _Interface>
|
||||
inline constexpr bool __is_value_v<__ireference<_Interface>> = false;
|
||||
|
||||
template <class _Interface>
|
||||
inline constexpr bool __is_lvalue_reference_v = false;
|
||||
|
||||
template <class _Interface>
|
||||
inline constexpr bool __is_lvalue_reference_v<__ireference<_Interface const>> = true;
|
||||
|
||||
template <class _Interface>
|
||||
inline constexpr bool __is_lvalue_reference_v<_Interface&> = true;
|
||||
|
||||
//!
|
||||
//! __bases_of: get the list of base interface for an interface, including itself
|
||||
//! and __iunknown.
|
||||
//!
|
||||
template <class _Interface, class _Fn>
|
||||
using __bases_of _CCCL_NODEBUG_ALIAS = //
|
||||
::cuda::std::__type_call< //
|
||||
::cuda::std::__type_concat< //
|
||||
::cuda::std::__type_list<__iunknown, ::cuda::std::remove_const_t<_Interface>>,
|
||||
typename _Interface::template __ibases<__make_type_list>>,
|
||||
_Fn>;
|
||||
|
||||
//!
|
||||
//! interface subsumption
|
||||
//!
|
||||
template <class _Interface1, class _Interface2>
|
||||
inline constexpr bool __subsumes = false;
|
||||
|
||||
template <class _Interface>
|
||||
inline constexpr bool __subsumes<_Interface, _Interface> = true;
|
||||
|
||||
template <class... _Set>
|
||||
inline constexpr bool __subsumes<__iset_<_Set...>, __iset_<_Set...>> = true;
|
||||
|
||||
template <class... _Subset, class... _Superset>
|
||||
inline constexpr bool __subsumes<__iset_<_Subset...>, __iset_<_Superset...>> =
|
||||
::cuda::std::__type_set_contains_v<::cuda::std::__make_type_set<_Superset...>, _Subset...>;
|
||||
|
||||
//!
|
||||
//! __extension_of: Checks if one interface is an extension of another.
|
||||
//!
|
||||
//! An interface \c A is considered an extension of another \c B if \c B
|
||||
//! can be found by recursively searching the base interfaces of \c A.
|
||||
//! `__iset<As...>` is an extension of `__iset<Bs...>` if `Bs...` is a subset
|
||||
//! of `As...`.
|
||||
//!
|
||||
//! \note An interface is considered an extension of itself.
|
||||
//!
|
||||
template <class _Base>
|
||||
struct __has_base_fn
|
||||
{
|
||||
template <class... _Interfaces>
|
||||
using __call _CCCL_NODEBUG_ALIAS = ::cuda::std::bool_constant<::cuda::std::__is_included_in_v<_Base, _Interfaces...>>;
|
||||
};
|
||||
|
||||
template <class... _Bases>
|
||||
struct __has_base_fn<__iset_<_Bases...>>
|
||||
{
|
||||
using __bases_set _CCCL_NODEBUG_ALIAS = __iset_<_Bases...>;
|
||||
|
||||
template <class... _Interfaces>
|
||||
using __call _CCCL_NODEBUG_ALIAS = ::cuda::std::bool_constant<(__subsumes<__bases_set, _Interfaces> || ...)>;
|
||||
};
|
||||
|
||||
template <class _Derived, class _Base, class = void>
|
||||
inline constexpr bool __extension_of_v = false;
|
||||
|
||||
template <class _Derived, class _Base>
|
||||
inline constexpr bool
|
||||
__extension_of_v<_Derived,
|
||||
_Base,
|
||||
::cuda::std::enable_if_t<::cuda::std::is_class_v<_Derived>&& ::cuda::std::is_class_v<_Base>>> =
|
||||
__bases_of<_Derived, __has_base_fn<::cuda::std::remove_const_t<_Base>>>::value;
|
||||
|
||||
template <class _Derived, class _Base>
|
||||
_CCCL_CONCEPT __extension_of = __extension_of_v<_Derived, _Base>;
|
||||
|
||||
//!
|
||||
//! interface
|
||||
//!
|
||||
template <template <class...> class _Interface, class... _Bases, size_t Size, size_t Align>
|
||||
struct __basic_interface<_Interface, __extends<_Bases...>, Size, Align>
|
||||
{
|
||||
static constexpr size_t size = (::cuda::std::max) ({Size, _Bases::size...});
|
||||
static constexpr size_t align = (::cuda::std::max) ({Align, _Bases::align...});
|
||||
|
||||
template <class... _Super>
|
||||
using __rebind _CCCL_NODEBUG_ALIAS = _Interface<_Super...>;
|
||||
|
||||
template <class _Fn>
|
||||
using __ibases _CCCL_NODEBUG_ALIAS =
|
||||
::cuda::std::__type_call<::cuda::std::__type_concat<__bases_of<_Bases, __make_type_list>...>, _Fn>;
|
||||
|
||||
template <class _Tp>
|
||||
using overrides _CCCL_NODEBUG_ALIAS = __overrides_for<_Tp>;
|
||||
};
|
||||
|
||||
//!
|
||||
//! __is_interface
|
||||
//!
|
||||
template <template <class...> class _Interface, class _Extends, size_t _Size, size_t _Align>
|
||||
_CCCL_HOST_DEVICE_API auto __is_interface_test(__basic_interface<_Interface, _Extends, _Size, _Align> const&) -> void;
|
||||
|
||||
// clang-format off
|
||||
template <class _Tp>
|
||||
_CCCL_CONCEPT __is_interface =
|
||||
_CCCL_REQUIRES_EXPR((_Tp), _Tp& __value)
|
||||
(
|
||||
(::cuda::__is_interface_test(__value))
|
||||
);
|
||||
// clang-format on
|
||||
|
||||
//!
|
||||
//! __unique_interfaces
|
||||
//!
|
||||
//! Given an interface, return a list that contains the interface and all its
|
||||
//! bases, but with duplicates removed.
|
||||
//!
|
||||
template <class _Interface, class _Fn = __make_type_list>
|
||||
using __unique_interfaces _CCCL_NODEBUG_ALIAS = ::cuda::std::__type_apply<
|
||||
_Fn,
|
||||
::cuda::std::__as_type_list<__bases_of<_Interface, ::cuda::std::__type_quote<::cuda::std::__make_type_set>>>>;
|
||||
|
||||
//!
|
||||
//! __index_of_base: find the index of an interface in a list of unique interfaces
|
||||
//!
|
||||
[[nodiscard]] _CCCL_HOST_DEVICE_API constexpr auto __find_index(::cuda::std::initializer_list<bool> __il) -> size_t
|
||||
{
|
||||
auto __it = ::cuda::std::find(__il.begin(), __il.end(), true);
|
||||
return static_cast<size_t>(__it - __il.begin());
|
||||
}
|
||||
|
||||
template <class _Interface>
|
||||
struct __find_index_of_base
|
||||
{
|
||||
template <class... _Interfaces>
|
||||
static constexpr size_t __index = __find_index({__subsumes<_Interface, _Interfaces>...});
|
||||
|
||||
template <class... _Interfaces>
|
||||
using __call _CCCL_NODEBUG_ALIAS = ::cuda::std::integral_constant<size_t, __index<_Interfaces...>>;
|
||||
};
|
||||
|
||||
template <class _Interface, class _Super>
|
||||
using __index_of_base _CCCL_NODEBUG_ALIAS =
|
||||
::cuda::std::__type_apply<__find_index_of_base<_Interface>, __unique_interfaces<_Super>>;
|
||||
|
||||
template <class...>
|
||||
struct __iempty : __basic_interface<__iempty>
|
||||
{};
|
||||
|
||||
#if _CCCL_COMPILER(NVHPC)
|
||||
|
||||
template <class _Interface>
|
||||
struct __vptr_for_impl
|
||||
{
|
||||
using type = typename _Interface::template overrides<__remove_ireference_t<_Interface>>::__vptr_t;
|
||||
};
|
||||
|
||||
template <class _Interface>
|
||||
using __vptr_for _CCCL_NODEBUG_ALIAS = typename __vptr_for_impl<_Interface>::type;
|
||||
|
||||
#else // ^^^ _CCCL_COMPILER(NVHPC) ^^^ / vvv !_CCCL_COMPILER(NVHPC) vvv
|
||||
|
||||
template <class _Interface>
|
||||
using __vptr_for _CCCL_NODEBUG_ALIAS = typename __overrides_for_t<_Interface>::__vptr_t;
|
||||
|
||||
#endif // !_CCCL_COMPILER(NVHPC)
|
||||
|
||||
//!
|
||||
//! interface satisfaction
|
||||
//!
|
||||
template <class _Tp>
|
||||
struct __satisfaction_fn
|
||||
{
|
||||
template <class _Interface>
|
||||
using __does_not_satisfy _CCCL_NODEBUG_ALIAS =
|
||||
::cuda::std::_Not<::cuda::std::_IsValidExpansion<__overrides_for_t, _Interface, _Tp>>;
|
||||
|
||||
// Try to find an unsatisfied interface. If we find one, we return it (it's at
|
||||
// the front of the list returned from __type_find_if). If we don't find one
|
||||
// (that is, if the returned list is empty), we return __iempty<>.
|
||||
template <class... _Interfaces>
|
||||
using __call _CCCL_NODEBUG_ALIAS = ::cuda::std::__type_front< // take the front of the list
|
||||
::cuda::std::__type_push_back< // add __iempty<> to the end of the list
|
||||
::cuda::std::__type_find_if< // find the first unsatisfied interface if any, returns a list
|
||||
::cuda::std::__type_list<_Interfaces...>,
|
||||
::cuda::std::__type_quote1<__does_not_satisfy>>,
|
||||
__iempty<>>>;
|
||||
};
|
||||
|
||||
template <class _Interface, class _Tp, class = void>
|
||||
struct __unsatisfied_interface
|
||||
{};
|
||||
|
||||
template <class _Interface, class _Tp>
|
||||
struct __unsatisfied_interface<_Interface, _Tp, ::cuda::std::enable_if_t<::cuda::std::is_class_v<_Interface>>>
|
||||
{
|
||||
using type _CCCL_NODEBUG_ALIAS = __unique_interfaces<_Interface, __satisfaction_fn<_Tp>>;
|
||||
};
|
||||
|
||||
template <class _Interface, class _Tp>
|
||||
struct __unsatisfied_interface<_Interface*, _Tp*> : __unsatisfied_interface<_Interface, _Tp>
|
||||
{};
|
||||
|
||||
template <class _Interface, class _Tp>
|
||||
struct __unsatisfied_interface<_Interface const*, _Tp const*> : __unsatisfied_interface<_Interface, _Tp>
|
||||
{};
|
||||
|
||||
template <class _Interface, class _Tp>
|
||||
struct __unsatisfied_interface<_Interface&, _Tp> : __unsatisfied_interface<_Interface, _Tp>
|
||||
{};
|
||||
|
||||
template <class _Tp, class _Interface>
|
||||
_CCCL_CONCEPT __has_overrides = ::cuda::std::_IsValidExpansion<__overrides_for_t, _Interface, _Tp>::value;
|
||||
|
||||
//! The \c __satisfies concept checks if a type \c _Tp satisfies an interface
|
||||
//! \c _Interface. It does this by trying to instantiate
|
||||
//! `__overrides_for_t<_X, _Tp>` for all \c _X, where \c _X is \c _Interface or
|
||||
//! one of its bases. If any of the \c __overrides_for_t instantiations are ill-
|
||||
//! formed, then \c _Tp does not satisfy \c _Interface.
|
||||
//!
|
||||
//! \c __satisfies is implemented by searching through the list of interfaces for
|
||||
//! one that \c _Tp does not satisfy. If such an interface is found, the concept
|
||||
//! check fails in such a way as to hopefully tell the user which interface is
|
||||
//! not satisfied and why.
|
||||
template <class _Tp,
|
||||
class _Interface,
|
||||
class UnsatisfiedInterface = ::cuda::std::__type<__unsatisfied_interface<_Interface, _Tp>>>
|
||||
_CCCL_CONCEPT __satisfies = __has_overrides<_Tp, UnsatisfiedInterface>;
|
||||
|
||||
//!
|
||||
//! __interface_of
|
||||
//!
|
||||
template <class _Super>
|
||||
struct __make_interface_fn
|
||||
{
|
||||
static_assert(::cuda::std::is_class_v<_Super>, "expected a class type");
|
||||
template <class... _Interfaces>
|
||||
using __call _CCCL_NODEBUG_ALIAS = ::cuda::__inherit<__rebind_interface<_Interfaces, _Super>...>;
|
||||
};
|
||||
|
||||
// Given an interface `_I<>`, let `_Bs<>...` be the list of types consisting
|
||||
// of all of `_I<>`'s unique bases. Then `__interface_of<_I<>>` is the
|
||||
// type `__inherit<_I<_I<>>, _Bs<_I<>>...>`. That is, it transforms the
|
||||
// unspecialized interfaces into ones specialized for `_I<>` and then
|
||||
// makes a type that inherits publicly from all of them.
|
||||
template <class _Interface>
|
||||
using __interface_of _CCCL_NODEBUG_ALIAS = __unique_interfaces<_Interface, __make_interface_fn<_Interface>>;
|
||||
|
||||
//!
|
||||
//! interface_cast
|
||||
//!
|
||||
//! given a `__basic_any<X<>>` object `o`, `interface_cast<Y>(o)` return a
|
||||
//! reference to the (empty) sub-object of type `Y<X<>>`, from which
|
||||
//! `__basic_any<X<>>` inherits, where `Y<>` is an interface that `X<>` extends.
|
||||
//!
|
||||
template <class _Interface>
|
||||
struct __interface_cast_fn;
|
||||
|
||||
template <template <class...> class _Interface>
|
||||
struct __interface_cast_fn<_Interface<>>
|
||||
{
|
||||
template <class _Super>
|
||||
[[nodiscard]] _CCCL_NODEBUG_API auto operator()(_Interface<_Super>&& __self) const noexcept -> _Interface<_Super>&&
|
||||
{
|
||||
return ::cuda::std::move(__self);
|
||||
}
|
||||
|
||||
template <class _Super>
|
||||
[[nodiscard]] _CCCL_NODEBUG_API auto operator()(_Interface<_Super>& __self) const noexcept -> _Interface<_Super>&
|
||||
{
|
||||
return __self;
|
||||
}
|
||||
|
||||
template <class _Super>
|
||||
[[nodiscard]] _CCCL_NODEBUG_API auto operator()(_Interface<_Super> const& __self _CCCL_LIFETIMEBOUND) noexcept
|
||||
-> _Interface<_Super> const&
|
||||
{
|
||||
return __self;
|
||||
}
|
||||
};
|
||||
|
||||
_CCCL_TEMPLATE(template <class...> class _Interface, class Object)
|
||||
_CCCL_REQUIRES(
|
||||
__is_interface<_Interface<>> _CCCL_AND ::cuda::std::__is_callable_v<__interface_cast_fn<_Interface<>>, Object>)
|
||||
[[nodiscard]] _CCCL_NODEBUG_API auto __interface_cast(Object&& __obj) noexcept -> decltype(auto)
|
||||
{
|
||||
return __interface_cast_fn<_Interface<>>{}(::cuda::std::forward<Object>(__obj));
|
||||
}
|
||||
|
||||
_CCCL_TEMPLATE(class _Interface, class Object)
|
||||
_CCCL_REQUIRES(
|
||||
__is_interface<_Interface> _CCCL_AND ::cuda::std::__is_callable_v<__interface_cast_fn<_Interface>, Object>)
|
||||
[[nodiscard]] _CCCL_NODEBUG_API auto __interface_cast(Object&& __obj) noexcept -> decltype(auto)
|
||||
{
|
||||
return __interface_cast_fn<_Interface>{}(::cuda::std::forward<Object>(__obj));
|
||||
}
|
||||
_CCCL_END_NAMESPACE_CUDA
|
||||
|
||||
#include <cuda/std/__cccl/epilogue.h>
|
||||
|
||||
#endif // _CUDA___UTILITY_BASIC_ANY_INTERFACES_H
|
||||
@@ -0,0 +1,182 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of libcu++, the C++ Standard Library for your entire system,
|
||||
// under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
// SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef _CUDA___UTILITY_BASIC_ANY_ISET_H
|
||||
#define _CUDA___UTILITY_BASIC_ANY_ISET_H
|
||||
|
||||
#include <cuda/std/detail/__config>
|
||||
|
||||
#if defined(_CCCL_IMPLICIT_SYSTEM_HEADER_GCC)
|
||||
# pragma GCC system_header
|
||||
#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_CLANG)
|
||||
# pragma clang system_header
|
||||
#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_MSVC)
|
||||
# pragma system_header
|
||||
#endif // no system header
|
||||
|
||||
#include <cuda/__type_traits/is_specialization_of.h>
|
||||
#include <cuda/__utility/__basic_any/basic_any_fwd.h>
|
||||
#include <cuda/__utility/__basic_any/rtti.h>
|
||||
#include <cuda/__utility/__basic_any/tagged_ptr.h>
|
||||
#include <cuda/__utility/__basic_any/virtual_tables.h>
|
||||
#include <cuda/std/__type_traits/type_list.h>
|
||||
#include <cuda/std/__type_traits/type_set.h>
|
||||
|
||||
#include <cuda/std/__cccl/prologue.h>
|
||||
|
||||
_CCCL_BEGIN_NAMESPACE_CUDA
|
||||
|
||||
//!
|
||||
//! __iset_
|
||||
//!
|
||||
template <class... _Interfaces>
|
||||
struct __iset__
|
||||
{
|
||||
template <class...>
|
||||
struct __interface_ : __basic_interface<__interface_, __extends<_Interfaces...>>
|
||||
{};
|
||||
};
|
||||
|
||||
template <class... _Interfaces>
|
||||
struct __iset_ : __iset__<_Interfaces...>::template __interface_<>
|
||||
{};
|
||||
|
||||
// flatten any nested sets
|
||||
template <class _Interface>
|
||||
using __iset_flatten _CCCL_NODEBUG_ALIAS = ::cuda::std::__as_type_list<
|
||||
::cuda::std::
|
||||
conditional_t<__is_specialization_of_v<_Interface, __iset_>, _Interface, ::cuda::std::__type_list<_Interface>>>;
|
||||
|
||||
// flatten all sets into one, remove duplicates, and sort the elements.
|
||||
// TODO: sort!
|
||||
// template <class... _Interfaces>
|
||||
// using __iset _CCCL_NODEBUG_ALIAS = ::cuda::std::__type_call<
|
||||
// ::cuda::std::__type_unique<::cuda::std::__type_sort<::cuda::std::__type_concat<__iset_flatten<_Interfaces>...>>>,
|
||||
// ::cuda::std::__type_quote<__iset_>>;
|
||||
// GCC 7 had a problem with the original implementation, so we use a workaround.
|
||||
#if _CCCL_COMPILER(GCC, <, 10)
|
||||
template <class _Lhs, class _Rhs>
|
||||
struct __iset_cat;
|
||||
|
||||
template <class... _Lhs, class... _Rhs>
|
||||
struct __iset_cat<::cuda::std::__type_list<_Lhs...>, ::cuda::std::__type_list<_Rhs...>>
|
||||
{
|
||||
using type = ::cuda::std::__type_list<_Lhs..., _Rhs...>;
|
||||
};
|
||||
|
||||
template <class... _Interfaces>
|
||||
struct __iset_flatten_all;
|
||||
|
||||
template <>
|
||||
struct __iset_flatten_all<>
|
||||
{
|
||||
using type = ::cuda::std::__type_list<>;
|
||||
};
|
||||
|
||||
template <class... _Nested, class... _Rest>
|
||||
struct __iset_flatten_all<__iset_<_Nested...>, _Rest...>
|
||||
{
|
||||
using type = typename __iset_cat<typename __iset_flatten_all<_Nested...>::type,
|
||||
typename __iset_flatten_all<_Rest...>::type>::type;
|
||||
};
|
||||
|
||||
template <class _Interface, class... _Rest>
|
||||
struct __iset_flatten_all<_Interface, _Rest...>
|
||||
{
|
||||
using type =
|
||||
typename __iset_cat<::cuda::std::__type_list<_Interface>, typename __iset_flatten_all<_Rest...>::type>::type;
|
||||
};
|
||||
|
||||
template <class... _Interfaces>
|
||||
using __iset = ::cuda::std::__type_call<::cuda::std::__type_unique<typename __iset_flatten_all<_Interfaces...>::type>,
|
||||
::cuda::std::__type_quote<__iset_>>;
|
||||
#else // ^^^ _CCCL_COMPILER(GCC, <, 10) ^^^ / vvv _CCCL_COMPILER(GCC, >=, 10) vvv
|
||||
template <class... _Interfaces>
|
||||
using __iset =
|
||||
::cuda::std::__type_call<::cuda::std::__type_unique<::cuda::std::__type_concat<__iset_flatten<_Interfaces>...>>,
|
||||
::cuda::std::__type_quote<__iset_>>;
|
||||
#endif // _CCCL_COMPILER(GCC, >=, 10)
|
||||
|
||||
//!
|
||||
//! Virtual table pointers
|
||||
//!
|
||||
template <class... _Interfaces>
|
||||
struct __iset_vptr : __base_vptr
|
||||
{
|
||||
using __iset_vtable _CCCL_NODEBUG_ALIAS = __vtable_for<__iset_<_Interfaces...>>;
|
||||
|
||||
__iset_vptr() = default;
|
||||
|
||||
_CCCL_HOST_DEVICE_API constexpr __iset_vptr(__iset_vtable const* __vptr) noexcept
|
||||
: __base_vptr(__vptr)
|
||||
{}
|
||||
|
||||
_CCCL_HOST_DEVICE_API constexpr __iset_vptr(__base_vptr __vptr) noexcept
|
||||
: __base_vptr(__vptr)
|
||||
{}
|
||||
|
||||
// Permit narrowing conversions from a super-set __vptr. Warning: we can't
|
||||
// simply constrain this because then the ctor from __base_vptr would be
|
||||
// selected instead, giving the wrong result.
|
||||
template <class... _Others>
|
||||
_CCCL_HOST_DEVICE_API __iset_vptr(__iset_vptr<_Others...> __vptr) noexcept
|
||||
: __base_vptr(__vptr->__query_interface(__iunknown()))
|
||||
{
|
||||
static_assert(::cuda::std::__type_set_contains_v<::cuda::std::__make_type_set<_Others...>, _Interfaces...>);
|
||||
_CCCL_ASSERT(__vptr_->__kind_ == __vtable_kind::__rtti && __vptr_->__cookie_ == 0xDEADBEEF,
|
||||
"query_interface returned a bad pointer to the __iunknown vtable");
|
||||
}
|
||||
|
||||
[[nodiscard]] _CCCL_NODEBUG_API constexpr auto operator->() const noexcept -> __iset_vptr const*
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
template <class _Interface>
|
||||
[[nodiscard]] _CCCL_NODEBUG_API constexpr auto __query_interface(_Interface) const noexcept -> __vptr_for<_Interface>
|
||||
{
|
||||
if (__vptr_->__kind_ == __vtable_kind::__normal)
|
||||
{
|
||||
return static_cast<__iset_vtable const*>(__vptr_)->__query_interface(_Interface{});
|
||||
}
|
||||
else
|
||||
{
|
||||
return static_cast<__rtti const*>(__vptr_)->__query_interface(_Interface{});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <class... _Interfaces>
|
||||
struct __tagged_ptr<__iset_vptr<_Interfaces...>>
|
||||
{
|
||||
_CCCL_NODEBUG_API auto __set(__iset_vptr<_Interfaces...> __vptr, bool __flag) noexcept -> void
|
||||
{
|
||||
__ptr_ = reinterpret_cast<uintptr_t>(__vptr.__vptr_) | uintptr_t(__flag);
|
||||
}
|
||||
|
||||
[[nodiscard]] _CCCL_NODEBUG_API auto __get() const noexcept -> __iset_vptr<_Interfaces...>
|
||||
{
|
||||
// NOLINTNEXTLINE(performance-no-int-to-ptr)
|
||||
return __iset_vptr<_Interfaces...>{reinterpret_cast<__rtti_base const*>(__ptr_ & ~uintptr_t(1))};
|
||||
}
|
||||
|
||||
[[nodiscard]] _CCCL_NODEBUG_API auto __flag() const noexcept -> bool
|
||||
{
|
||||
return static_cast<bool>(__ptr_ & uintptr_t(1));
|
||||
}
|
||||
|
||||
uintptr_t __ptr_ = 0;
|
||||
};
|
||||
|
||||
_CCCL_END_NAMESPACE_CUDA
|
||||
|
||||
#include <cuda/std/__cccl/epilogue.h>
|
||||
|
||||
#endif // _CUDA___UTILITY_BASIC_ANY_ISET_H
|
||||
@@ -0,0 +1,64 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of libcu++, the C++ Standard Library for your entire system,
|
||||
// under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
// SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef _CUDA___UTILITY_BASIC_ANY_OVERRIDES_H
|
||||
#define _CUDA___UTILITY_BASIC_ANY_OVERRIDES_H
|
||||
|
||||
#include <cuda/std/detail/__config>
|
||||
|
||||
#if defined(_CCCL_IMPLICIT_SYSTEM_HEADER_GCC)
|
||||
# pragma GCC system_header
|
||||
#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_CLANG)
|
||||
# pragma clang system_header
|
||||
#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_MSVC)
|
||||
# pragma system_header
|
||||
#endif // no system header
|
||||
|
||||
#include <cuda/__utility/__basic_any/basic_any_fwd.h>
|
||||
#include <cuda/std/__tuple_dir/ignore.h>
|
||||
#include <cuda/std/__type_traits/is_const.h>
|
||||
|
||||
#include <cuda/std/__cccl/prologue.h>
|
||||
|
||||
_CCCL_BEGIN_NAMESPACE_CUDA
|
||||
|
||||
template <class _Interface, class _Tp = __remove_ireference_t<_Interface>>
|
||||
using __overrides_for_t _CCCL_NODEBUG_ALIAS = typename _Interface::template overrides<_Tp>;
|
||||
|
||||
//!
|
||||
//! __overrides_for
|
||||
//!
|
||||
template <class _InterfaceOrModel, class... _VirtualFnsOrOverrides>
|
||||
struct __overrides_list
|
||||
{
|
||||
static_assert(!::cuda::std::is_const_v<_InterfaceOrModel>, "expected a class type");
|
||||
using __vtable _CCCL_NODEBUG_ALIAS = __basic_vtable<_InterfaceOrModel, _VirtualFnsOrOverrides::value...>;
|
||||
using __vptr_t _CCCL_NODEBUG_ALIAS = __vtable const*;
|
||||
};
|
||||
|
||||
template <class... _Interfaces>
|
||||
struct __overrides_list<__iset_<_Interfaces...>>
|
||||
{
|
||||
using __vtable _CCCL_NODEBUG_ALIAS = __basic_vtable<__iset_<_Interfaces...>>;
|
||||
using __vptr_t _CCCL_NODEBUG_ALIAS = __iset_vptr<_Interfaces...>;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct __overrides_list<__iunknown>
|
||||
{
|
||||
using __vtable _CCCL_NODEBUG_ALIAS = ::cuda::std::__ignore_t; // no vtable, rtti is added explicitly in __vtable_tuple
|
||||
using __vptr_t _CCCL_NODEBUG_ALIAS = __rtti const*;
|
||||
};
|
||||
|
||||
_CCCL_END_NAMESPACE_CUDA
|
||||
|
||||
#include <cuda/std/__cccl/epilogue.h>
|
||||
|
||||
#endif // _CUDA___UTILITY_BASIC_ANY_OVERRIDES_H
|
||||
@@ -0,0 +1,280 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of libcu++, the C++ Standard Library for your entire system,
|
||||
// under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef _CUDA___UTILITY_BASIC_ANY_RTTI_H
|
||||
#define _CUDA___UTILITY_BASIC_ANY_RTTI_H
|
||||
|
||||
#include <cuda/std/detail/__config>
|
||||
|
||||
#if defined(_CCCL_IMPLICIT_SYSTEM_HEADER_GCC)
|
||||
# pragma GCC system_header
|
||||
#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_CLANG)
|
||||
# pragma clang system_header
|
||||
#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_MSVC)
|
||||
# pragma system_header
|
||||
#endif // no system header
|
||||
|
||||
#include <cuda/__utility/__basic_any/basic_any_fwd.h>
|
||||
#include <cuda/__utility/__basic_any/interfaces.h>
|
||||
#include <cuda/__utility/__basic_any/virtual_ptrs.h>
|
||||
#include <cuda/__utility/immovable.h>
|
||||
#include <cuda/std/__cccl/unreachable.h>
|
||||
#include <cuda/std/__exception/terminate.h>
|
||||
#include <cuda/std/__utility/typeid.h>
|
||||
|
||||
#include <nv/target>
|
||||
|
||||
#if _CCCL_HOSTED()
|
||||
# include <typeinfo> // IWYU pragma: keep (for std::bad_cast)
|
||||
#endif // _CCCL_HOSTED()
|
||||
|
||||
#include <cuda/std/__cccl/prologue.h>
|
||||
|
||||
_CCCL_BEGIN_NAMESPACE_CUDA
|
||||
|
||||
//!
|
||||
//! __iunknown: Logically, the root of all interfaces.
|
||||
//!
|
||||
struct __iunknown : __basic_interface<::cuda::std::__type_always<__iunknown>::__call>
|
||||
{};
|
||||
|
||||
#if _CCCL_HAS_EXCEPTIONS()
|
||||
//!
|
||||
//! __bad_any_cast
|
||||
//!
|
||||
struct __bad_any_cast : ::std::bad_cast
|
||||
{
|
||||
__bad_any_cast() noexcept = default;
|
||||
__bad_any_cast(__bad_any_cast const&) noexcept = default;
|
||||
~__bad_any_cast() noexcept override = default;
|
||||
auto operator=(__bad_any_cast const&) noexcept -> __bad_any_cast& = default;
|
||||
|
||||
auto what() const noexcept -> char const* override
|
||||
{
|
||||
return "cannot cast value to target type";
|
||||
}
|
||||
};
|
||||
|
||||
[[noreturn]] _CCCL_HOST_DEVICE_API inline void __throw_bad_any_cast()
|
||||
{
|
||||
NV_IF_ELSE_TARGET(NV_IS_HOST, (throw __bad_any_cast();), (::cuda::std::terminate();))
|
||||
}
|
||||
#else // ^^^ _CCCL_HAS_EXCEPTIONS() ^^^ / vvv !_CCCL_HAS_EXCEPTIONS() vvv
|
||||
[[noreturn]] _CCCL_HOST_DEVICE_API inline void __throw_bad_any_cast()
|
||||
{
|
||||
::cuda::std::terminate();
|
||||
}
|
||||
#endif // !_CCCL_HAS_EXCEPTIONS()
|
||||
|
||||
struct __rtti_base : __immovable
|
||||
{
|
||||
_CCCL_HOST_DEVICE_API constexpr __rtti_base(
|
||||
__vtable_kind __kind, uint16_t __nbr_interfaces, ::cuda::std::__type_info_ref __self) noexcept
|
||||
: __kind_(__kind)
|
||||
, __nbr_interfaces_(__nbr_interfaces)
|
||||
, __typeid_(&__self)
|
||||
{}
|
||||
|
||||
uint8_t __version_ = __basic_any_version;
|
||||
__vtable_kind __kind_ = __vtable_kind::__normal;
|
||||
uint16_t __nbr_interfaces_ = 0;
|
||||
uint32_t const __cookie_ = 0xDEADBEEF;
|
||||
::cuda::std::__type_info_ptr __typeid_ = nullptr;
|
||||
};
|
||||
|
||||
static_assert(sizeof(__rtti_base) == sizeof(uint64_t) + sizeof(void*));
|
||||
|
||||
// Used to map an interface typeid to a pointer to the vtable for that interface.
|
||||
struct __base_info
|
||||
{
|
||||
using __cast_fn_t = auto(__rtti const*) noexcept -> __base_vptr;
|
||||
|
||||
::cuda::std::__type_info_ptr __typeid_;
|
||||
union
|
||||
{
|
||||
__cast_fn_t* __cast_fn_; // used when __basic_any_version >= 1,
|
||||
__base_vptr __vptr_v0_; // used when __basic_any_version == 0
|
||||
};
|
||||
|
||||
[[nodiscard]] _CCCL_HOST_DEVICE_API auto __get_vptr(__rtti const* __rtti_ptr, uint8_t __version) const noexcept
|
||||
-> __base_vptr
|
||||
{
|
||||
return __version >= 1 ? __cast_fn_(__rtti_ptr) : __vptr_v0_;
|
||||
}
|
||||
|
||||
template <class _VTable, class _Interface>
|
||||
[[nodiscard]] _CCCL_HOST_DEVICE_API static auto __cast_fn_impl(__rtti const* __rtti_ptr) noexcept -> __base_vptr
|
||||
{
|
||||
return {static_cast<__vptr_for<_Interface>>(static_cast<_VTable const*>(__rtti_ptr))};
|
||||
}
|
||||
};
|
||||
|
||||
inline constexpr size_t __half_size_t_bits = sizeof(size_t) * CHAR_BIT / 2;
|
||||
|
||||
// The metadata for the type-erased object. All vtables have an rtti sub-object,
|
||||
// which contains a sub-object of this type.
|
||||
struct __object_metadata
|
||||
{
|
||||
size_t __size_ : __half_size_t_bits;
|
||||
size_t __align_ : __half_size_t_bits;
|
||||
::cuda::std::__type_info_ptr __object_typeid_;
|
||||
::cuda::std::__type_info_ptr __pointer_typeid_;
|
||||
::cuda::std::__type_info_ptr __const_pointer_typeid_;
|
||||
};
|
||||
|
||||
template <class _Tp>
|
||||
_CCCL_GLOBAL_CONSTANT __object_metadata __object_metadata_v = {
|
||||
sizeof(_Tp), alignof(_Tp), &_CCCL_TYPEID(_Tp), &_CCCL_TYPEID(_Tp*), &_CCCL_TYPEID(_Tp const*)};
|
||||
|
||||
template <class _Tp>
|
||||
_CCCL_HOST_DEVICE_API void __dtor_fn(void* __pv, bool __small) noexcept
|
||||
{
|
||||
__small ? static_cast<_Tp*>(__pv)->~_Tp() //
|
||||
: delete *static_cast<_Tp**>(__pv);
|
||||
}
|
||||
|
||||
// All vtables have an rtti sub-object. This object has several responsibilities:
|
||||
// * It contains the destructor for the type-erased object.
|
||||
// * It contains the metadata for the type-erased object.
|
||||
// * It contains a map from the base interfaces typeids to their vtables for use
|
||||
// in dynamic_cast-like functionality.
|
||||
struct __rtti : __rtti_base
|
||||
{
|
||||
template <class _Tp, class _Super, class... _Interfaces>
|
||||
_CCCL_NODEBUG_API constexpr __rtti(
|
||||
__tag<_Tp, _Super>, __tag<_Interfaces...>, __base_info const* __base_vptr_map) noexcept
|
||||
: __rtti_base{__vtable_kind::__rtti, sizeof...(_Interfaces), _CCCL_TYPEID(__rtti)}
|
||||
, __dtor_(&__dtor_fn<_Tp>)
|
||||
, __object_info_(&__object_metadata_v<_Tp>)
|
||||
, __interface_typeid_{&_CCCL_TYPEID(_Super)}
|
||||
, __base_vptr_map_{__base_vptr_map}
|
||||
{}
|
||||
|
||||
template <class... _Interfaces>
|
||||
[[nodiscard]] _CCCL_HOST_DEVICE_API auto __query_interface(__iset_<_Interfaces...>) const noexcept
|
||||
-> __vptr_for<__iset_<_Interfaces...>>
|
||||
{
|
||||
// Verify that every sub-interface in the requested set exists in the vtable.
|
||||
// TODO: Can it be done in a more efficient way?
|
||||
if ((__query_interface(_Interfaces{}) && ...))
|
||||
{
|
||||
return static_cast<__vptr_for<__iset_<_Interfaces...>>>(this);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Sequentially search the base_vptr_map for the requested interface by
|
||||
// comparing typeids. If the requested interface is found, return a pointer to
|
||||
// its vtable; otherwise, return nullptr.
|
||||
template <class _Interface>
|
||||
[[nodiscard]] _CCCL_HOST_DEVICE_API auto __query_interface(_Interface) const noexcept -> __vptr_for<_Interface>
|
||||
{
|
||||
// On sane implementations, comparing type_info objects first compares their
|
||||
// addresses and, if that fails, it does a string comparison. What we want is
|
||||
// to check _all_ the addresses first, and only if they all fail, resort to
|
||||
// string comparisons. So do two passes over the __base_vptr_map.
|
||||
constexpr ::cuda::std::__type_info_ref __id = _CCCL_TYPEID(_Interface);
|
||||
|
||||
for (size_t __i = 0; __i < __nbr_interfaces_; ++__i)
|
||||
{
|
||||
if (&__id == __base_vptr_map_[__i].__typeid_)
|
||||
{
|
||||
return static_cast<__vptr_for<_Interface>>(__base_vptr_map_[__i].__get_vptr(this, __version_));
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t __i = 0; __i < __nbr_interfaces_; ++__i)
|
||||
{
|
||||
if (__id == *__base_vptr_map_[__i].__typeid_)
|
||||
{
|
||||
return static_cast<__vptr_for<_Interface>>(__base_vptr_map_[__i].__get_vptr(this, __version_));
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void (*__dtor_)(void*, bool) noexcept = nullptr;
|
||||
__object_metadata const* __object_info_ = nullptr;
|
||||
::cuda::std::__type_info_ptr __interface_typeid_ = nullptr;
|
||||
__base_info const* __base_vptr_map_ = nullptr;
|
||||
};
|
||||
|
||||
template <size_t _NbrInterfaces>
|
||||
struct __rtti_ex : __rtti
|
||||
{
|
||||
template <class _Tp, class _Super, class... _Interfaces, class _VTable>
|
||||
_CCCL_HOST_DEVICE_API constexpr __rtti_ex(
|
||||
__tag<_Tp, _Super> __type, __tag<_Interfaces...> __ibases, _VTable const*) noexcept
|
||||
: __rtti{__type, __ibases, __base_vptr_array}
|
||||
, __base_vptr_array{{&_CCCL_TYPEID(_Interfaces), {&__base_info::__cast_fn_impl<_VTable, _Interfaces>}}...}
|
||||
{}
|
||||
|
||||
__base_info __base_vptr_array[_NbrInterfaces];
|
||||
};
|
||||
|
||||
//!
|
||||
//! __try_vptr_cast
|
||||
//!
|
||||
//! This function ignores const qualification on the source and destination
|
||||
//! interfaces.
|
||||
//!
|
||||
template <class _SrcInterface, class _DstInterface>
|
||||
[[nodiscard]] _CCCL_HOST_DEVICE_API auto __try_vptr_cast(__vptr_for<_SrcInterface> __src_vptr) noexcept
|
||||
-> __vptr_for<_DstInterface>
|
||||
{
|
||||
static_assert(::cuda::std::is_class_v<_SrcInterface> && ::cuda::std::is_class_v<_DstInterface>,
|
||||
"expected class types");
|
||||
if (__src_vptr == nullptr)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
else if constexpr (::cuda::std::is_same_v<_SrcInterface const, _DstInterface const>)
|
||||
{
|
||||
return __src_vptr;
|
||||
}
|
||||
else if constexpr (__extension_of<_SrcInterface, _DstInterface>)
|
||||
{
|
||||
//! Fast up-casts:
|
||||
return __src_vptr->__query_interface(_DstInterface());
|
||||
}
|
||||
else
|
||||
{
|
||||
//! Slow down-casts and cross-casts:
|
||||
__rtti const* __rtti_ptr = __src_vptr->__query_interface(__iunknown());
|
||||
return __rtti_ptr->__query_interface(_DstInterface());
|
||||
}
|
||||
}
|
||||
|
||||
template <class _SrcInterface, class _DstInterface>
|
||||
[[nodiscard]] _CCCL_HOST_DEVICE_API auto __vptr_cast(__vptr_for<_SrcInterface> __src_vptr) //
|
||||
noexcept(::cuda::std::is_same_v<_SrcInterface, _DstInterface>) //
|
||||
-> __vptr_for<_DstInterface>
|
||||
{
|
||||
if constexpr (::cuda::std::is_same_v<_SrcInterface, _DstInterface>)
|
||||
{
|
||||
return __src_vptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto __dst_vptr = __try_vptr_cast<_SrcInterface, _DstInterface>(__src_vptr);
|
||||
if (!__dst_vptr && __src_vptr)
|
||||
{
|
||||
__throw_bad_any_cast();
|
||||
}
|
||||
return __dst_vptr;
|
||||
}
|
||||
}
|
||||
|
||||
_CCCL_END_NAMESPACE_CUDA
|
||||
|
||||
#include <cuda/std/__cccl/epilogue.h>
|
||||
|
||||
#endif // _CUDA___UTILITY_BASIC_ANY_RTTI_H
|
||||
@@ -0,0 +1,324 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of libcu++, the C++ Standard Library for your entire system,
|
||||
// under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
// SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef _CUDA___UTILITY_BASIC_ANY_SEMIREGULAR_H
|
||||
#define _CUDA___UTILITY_BASIC_ANY_SEMIREGULAR_H
|
||||
|
||||
#include <cuda/std/detail/__config>
|
||||
|
||||
#if defined(_CCCL_IMPLICIT_SYSTEM_HEADER_GCC)
|
||||
# pragma GCC system_header
|
||||
#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_CLANG)
|
||||
# pragma clang system_header
|
||||
#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_MSVC)
|
||||
# pragma system_header
|
||||
#endif // no system header
|
||||
|
||||
#include <cuda/__utility/__basic_any/access.h>
|
||||
#include <cuda/__utility/__basic_any/basic_any_base.h>
|
||||
#include <cuda/__utility/__basic_any/basic_any_from.h>
|
||||
#include <cuda/__utility/__basic_any/basic_any_fwd.h>
|
||||
#include <cuda/__utility/__basic_any/conversions.h>
|
||||
#include <cuda/__utility/__basic_any/interfaces.h>
|
||||
#include <cuda/__utility/__basic_any/storage.h>
|
||||
#include <cuda/__utility/__basic_any/virtcall.h>
|
||||
#include <cuda/std/__concepts/concept_macros.h>
|
||||
#include <cuda/std/__concepts/convertible_to.h>
|
||||
#include <cuda/std/__concepts/copyable.h>
|
||||
#include <cuda/std/__concepts/equality_comparable.h>
|
||||
#include <cuda/std/__concepts/movable.h>
|
||||
#include <cuda/std/__memory/addressof.h>
|
||||
#include <cuda/std/__new/device_new.h>
|
||||
#include <cuda/std/__type_traits/always_false.h>
|
||||
#include <cuda/std/__type_traits/decay.h>
|
||||
#include <cuda/std/__type_traits/is_same.h>
|
||||
#include <cuda/std/__type_traits/type_identity.h>
|
||||
#include <cuda/std/__utility/typeid.h>
|
||||
#include <cuda/std/__utility/unreachable.h>
|
||||
|
||||
#include <cuda/std/__cccl/prologue.h>
|
||||
|
||||
_CCCL_BEGIN_NAMESPACE_CUDA
|
||||
|
||||
//!
|
||||
//! semi-regular overrides
|
||||
//!
|
||||
|
||||
//! @note We use `::cuda::std::enable_if_t` here instead of requires-clauses
|
||||
//! to avoid ABI differences between C++17 and C++20 modes.
|
||||
|
||||
_CCCL_EXEC_CHECK_DISABLE
|
||||
template <class _Tp>
|
||||
_CCCL_PUBLIC_API auto __move_fn(_Tp& __src, void* __dst) noexcept -> void
|
||||
{
|
||||
static_assert(::cuda::std::movable<_Tp>, "type must be movable");
|
||||
::new (__dst) _Tp(static_cast<_Tp&&>(__src));
|
||||
}
|
||||
|
||||
_CCCL_EXEC_CHECK_DISABLE
|
||||
template <class _Tp>
|
||||
[[nodiscard]] _CCCL_PUBLIC_API auto __try_move_fn(_Tp& __src, void* __dst, size_t __size, size_t __align) -> bool
|
||||
{
|
||||
static_assert(::cuda::std::movable<_Tp>, "type must be movable");
|
||||
if (::cuda::__is_small<_Tp>(__size, __align))
|
||||
{
|
||||
::new (__dst) _Tp(static_cast<_Tp&&>(__src));
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
::new (__dst)::cuda::std::type_identity_t<_Tp*>(new _Tp(static_cast<_Tp&&>(__src)));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
_CCCL_EXEC_CHECK_DISABLE
|
||||
template <class _Tp>
|
||||
[[nodiscard]] _CCCL_PUBLIC_API auto __copy_fn(_Tp const& __src, void* __dst, size_t __size, size_t __align) -> bool
|
||||
{
|
||||
static_assert(::cuda::std::copyable<_Tp>, "type must be copyable");
|
||||
if (::cuda::__is_small<_Tp>(__size, __align))
|
||||
{
|
||||
::new (__dst) _Tp(__src);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
::new (__dst)::cuda::std::type_identity_t<_Tp*>(new _Tp(__src));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
_CCCL_EXEC_CHECK_DISABLE
|
||||
template <class _Tp>
|
||||
[[nodiscard]] _CCCL_PUBLIC_API auto
|
||||
__equal_fn(_Tp const& __self, ::cuda::std::__type_info_ref __type, void const* __other)
|
||||
-> ::cuda::std::enable_if_t<::cuda::std::equality_comparable<_Tp>, bool>
|
||||
{
|
||||
if (_CCCL_TYPEID(_Tp) == __type)
|
||||
{
|
||||
return __self == *static_cast<_Tp const*>(__other);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
_CCCL_EXEC_CHECK_DISABLE
|
||||
template <class _From, class _To>
|
||||
[[nodiscard]] _CCCL_PUBLIC_API auto __conversion_fn(::cuda::std::type_identity_t<_From> __self)
|
||||
-> ::cuda::std::enable_if_t<::cuda::std::convertible_to<_From, _To>, _To>
|
||||
{
|
||||
return static_cast<_To>(static_cast<_From&&>(__self));
|
||||
}
|
||||
|
||||
//!
|
||||
//! semi-regular interfaces
|
||||
//!
|
||||
template <class...>
|
||||
struct __imovable : __basic_interface<__imovable>
|
||||
{
|
||||
template <class _Tp>
|
||||
using overrides _CCCL_NODEBUG_ALIAS = __overrides_for<_Tp, &::cuda::__try_move_fn<_Tp>, &::cuda::__move_fn<_Tp>>;
|
||||
|
||||
_CCCL_HOST_DEVICE_API auto __move_to(void* __pv) noexcept -> void
|
||||
{
|
||||
return ::cuda::__virtcall<&::cuda::__move_fn<__imovable>>(this, __pv);
|
||||
}
|
||||
|
||||
[[nodiscard]] _CCCL_HOST_DEVICE_API auto __move_to(void* __pv, size_t __size, size_t __align) -> bool
|
||||
{
|
||||
return ::cuda::__virtcall<&::cuda::__try_move_fn<__imovable>>(this, __pv, __size, __align);
|
||||
}
|
||||
};
|
||||
|
||||
template <class...>
|
||||
struct __icopyable : __basic_interface<__icopyable, __extends<__imovable<>>>
|
||||
{
|
||||
template <class _Tp>
|
||||
using overrides _CCCL_NODEBUG_ALIAS = __overrides_for<_Tp, &::cuda::__copy_fn<_Tp>>;
|
||||
|
||||
[[nodiscard]] _CCCL_HOST_DEVICE_API auto __copy_to(void* __pv, size_t __size, size_t __align) const -> bool
|
||||
{
|
||||
return ::cuda::__virtcall<&::cuda::__copy_fn<__icopyable>>(this, __pv, __size, __align);
|
||||
}
|
||||
};
|
||||
|
||||
template <class _Object>
|
||||
_CCCL_CONCEPT __non_polymorphic = (!__is_basic_any<_Object>) && (!__is_interface<_Object>);
|
||||
|
||||
template <class... _Super>
|
||||
struct __iequality_comparable;
|
||||
|
||||
struct iequality_comparable_base : __basic_interface<__iequality_comparable>
|
||||
{
|
||||
// These overloads are only necessary so that __iequality_comparable<> itself
|
||||
// satisfies the std::equality_comparable constraint that is used by the
|
||||
// `__iequality_comparable<>::overloads` alias template below.
|
||||
[[noreturn]] friend _CCCL_NODEBUG_API auto
|
||||
operator==(__iequality_comparable<> const&, __iequality_comparable<> const&) noexcept -> bool
|
||||
{
|
||||
::cuda::std::unreachable();
|
||||
}
|
||||
|
||||
[[noreturn]] friend _CCCL_NODEBUG_API auto
|
||||
operator!=(__iequality_comparable<> const&, __iequality_comparable<> const&) noexcept -> bool
|
||||
{
|
||||
::cuda::std::unreachable();
|
||||
}
|
||||
|
||||
// These are the overloads that get used when testing two `__basic_any` objects
|
||||
// for equality.
|
||||
_CCCL_TEMPLATE(class _ILeft, class _IRight)
|
||||
_CCCL_REQUIRES(__any_convertible_to<__basic_any<_ILeft> const&, __basic_any<_IRight> const&>
|
||||
|| __any_convertible_to<__basic_any<_IRight> const&, __basic_any<_ILeft> const&>)
|
||||
[[nodiscard]] _CCCL_HOST_DEVICE_API friend auto
|
||||
operator==(__iequality_comparable<_ILeft> const& __lhs, __iequality_comparable<_IRight> const& __rhs) noexcept -> bool
|
||||
{
|
||||
auto const& __other = ::cuda::__basic_any_from(__rhs);
|
||||
constexpr auto __eq = &::cuda::__equal_fn<__iequality_comparable<_ILeft>>;
|
||||
return ::cuda::__virtcall<__eq>(&__lhs, __other.type(), __basic_any_access::__get_optr(__other));
|
||||
}
|
||||
|
||||
_CCCL_TEMPLATE(class _ILeft, class _IRight)
|
||||
_CCCL_REQUIRES(__any_convertible_to<__basic_any<_ILeft> const&, __basic_any<_IRight> const&>
|
||||
|| __any_convertible_to<__basic_any<_IRight> const&, __basic_any<_ILeft> const&>)
|
||||
[[nodiscard]] _CCCL_NODEBUG_API friend auto
|
||||
operator!=(__iequality_comparable<_ILeft> const& __lhs, __iequality_comparable<_IRight> const& __rhs) noexcept -> bool
|
||||
{
|
||||
return !(__lhs == __rhs);
|
||||
}
|
||||
|
||||
// These are the overloads that get used when testing a `__basic_any` object
|
||||
// against a non-type-erased object.
|
||||
//
|
||||
// Q: Why require that the __basic_any wrapper is not convertible to _Object?
|
||||
//
|
||||
// A: If there is a user-defined conversion from the __basic_any type to _Object
|
||||
// such that we can use _Object's symmetric equality comparison operator, that
|
||||
// should be preferred. _Object may be another kind of wrapper object, in which
|
||||
// case using the address of the **wrapper** object for the comparison (as
|
||||
// opposed to the address of the wrapped object) is probably wrong.
|
||||
_CCCL_TEMPLATE(class _Interface, class _Object, class _Self = __basic_any_from_t<__iequality_comparable<_Interface>>)
|
||||
_CCCL_REQUIRES(__non_polymorphic<_Object> _CCCL_AND(!::cuda::std::convertible_to<_Self, _Object>)
|
||||
_CCCL_AND __satisfies<_Object, _Interface>)
|
||||
[[nodiscard]] _CCCL_HOST_DEVICE_API friend auto
|
||||
operator==(__iequality_comparable<_Interface> const& __lhs, _Object const& __rhs) -> bool
|
||||
{
|
||||
constexpr auto __eq = &::cuda::__equal_fn<__iequality_comparable<_Interface>>;
|
||||
return ::cuda::__virtcall<__eq>(&__lhs, _CCCL_TYPEID(_Object), ::cuda::std::addressof(__rhs));
|
||||
}
|
||||
|
||||
_CCCL_TEMPLATE(class _Interface, class _Object, class _Self = __basic_any_from_t<__iequality_comparable<_Interface>>)
|
||||
_CCCL_REQUIRES(__non_polymorphic<_Object> _CCCL_AND(!::cuda::std::convertible_to<_Self, _Object>)
|
||||
_CCCL_AND __satisfies<_Object, _Interface>)
|
||||
[[nodiscard]] _CCCL_HOST_DEVICE_API friend auto
|
||||
operator==(_Object const& __lhs, __iequality_comparable<_Interface> const& __rhs) noexcept -> bool
|
||||
{
|
||||
constexpr auto __eq = &::cuda::__equal_fn<__iequality_comparable<_Interface>>;
|
||||
return ::cuda::__virtcall<__eq>(&__rhs, _CCCL_TYPEID(_Object), ::cuda::std::addressof(__lhs));
|
||||
}
|
||||
|
||||
_CCCL_TEMPLATE(class _Interface, class _Object, class _Self = __basic_any_from_t<__iequality_comparable<_Interface>>)
|
||||
_CCCL_REQUIRES(__non_polymorphic<_Object> _CCCL_AND(!::cuda::std::convertible_to<_Self, _Object>)
|
||||
_CCCL_AND __satisfies<_Object, _Interface>)
|
||||
[[nodiscard]] _CCCL_NODEBUG_API friend auto
|
||||
operator!=(__iequality_comparable<_Interface> const& __lhs, _Object const& __rhs) noexcept -> bool
|
||||
{
|
||||
return !(__lhs == __rhs);
|
||||
}
|
||||
|
||||
_CCCL_TEMPLATE(class _Interface, class _Object, class _Self = __basic_any_from_t<__iequality_comparable<_Interface>>)
|
||||
_CCCL_REQUIRES(__non_polymorphic<_Object> _CCCL_AND(!::cuda::std::convertible_to<_Self, _Object>)
|
||||
_CCCL_AND __satisfies<_Object, _Interface>)
|
||||
[[nodiscard]] _CCCL_NODEBUG_API friend auto
|
||||
operator!=(_Object const& __lhs, __iequality_comparable<_Interface> const& __rhs) noexcept -> bool
|
||||
{
|
||||
return !(__lhs == __rhs);
|
||||
}
|
||||
|
||||
_CCCL_TEMPLATE(class _Tp)
|
||||
_CCCL_REQUIRES(::cuda::std::equality_comparable<_Tp>)
|
||||
using overrides _CCCL_NODEBUG_ALIAS = __overrides_for<_Tp, &::cuda::__equal_fn<_Tp>>;
|
||||
};
|
||||
|
||||
template <class... _Super>
|
||||
struct __iequality_comparable : iequality_comparable_base
|
||||
{};
|
||||
|
||||
struct __self; // a nice placeholder type
|
||||
|
||||
template <class _CvSelf, class _To>
|
||||
struct __iconvertible_to_
|
||||
{
|
||||
static_assert(::cuda::std::is_same_v<::cuda::std::decay_t<_CvSelf>, __self>,
|
||||
"The first template parameter to __iconvertible_to must be the placeholder type "
|
||||
"cuda::__self, possibly with cv- and/or ref-qualifiers");
|
||||
};
|
||||
|
||||
template <class _To>
|
||||
struct __iconvertible_to_<__self&&, _To>
|
||||
{
|
||||
static_assert(::cuda::std::__always_false_v<_To>, "rvalue-qualified conversion operations are not yet supported");
|
||||
};
|
||||
|
||||
template <class _To>
|
||||
struct __iconvertible_to_<__self, _To>
|
||||
{
|
||||
template <class...>
|
||||
struct __interface_ : __basic_interface<__interface_>
|
||||
{
|
||||
[[nodiscard]] _CCCL_HOST_DEVICE_API operator _To()
|
||||
{
|
||||
return ::cuda::__virtcall<::cuda::__conversion_fn<__interface_, _To>>(this);
|
||||
}
|
||||
|
||||
template <class _From>
|
||||
using overrides = __overrides_for<_From, &::cuda::__conversion_fn<_From, _To>>;
|
||||
};
|
||||
};
|
||||
|
||||
template <class _To>
|
||||
struct __iconvertible_to_<__self&, _To>
|
||||
{
|
||||
template <class...>
|
||||
struct __interface_ : __basic_interface<__interface_>
|
||||
{
|
||||
[[nodiscard]] _CCCL_HOST_DEVICE_API operator _To() &
|
||||
{
|
||||
return ::cuda::__virtcall<&::cuda::__conversion_fn<__interface_&, _To>>(this);
|
||||
}
|
||||
|
||||
template <class _From>
|
||||
using overrides = __overrides_for<_From, &::cuda::__conversion_fn<_From&, _To>>;
|
||||
};
|
||||
};
|
||||
|
||||
template <class _To>
|
||||
struct __iconvertible_to_<__self const&, _To>
|
||||
{
|
||||
template <class...>
|
||||
struct __interface_ : __basic_interface<__interface_>
|
||||
{
|
||||
[[nodiscard]] _CCCL_HOST_DEVICE_API operator _To() const&
|
||||
{
|
||||
return ::cuda::__virtcall<&::cuda::__conversion_fn<__interface_ const&, _To>>(this);
|
||||
}
|
||||
|
||||
template <class _From>
|
||||
using overrides = __overrides_for<_From, &::cuda::__conversion_fn<_From const&, _To>>;
|
||||
};
|
||||
};
|
||||
|
||||
template <class _From, class _To>
|
||||
using __iconvertible_to _CCCL_NODEBUG_ALIAS = typename __iconvertible_to_<_From, _To>::template __interface_<>;
|
||||
_CCCL_END_NAMESPACE_CUDA
|
||||
|
||||
#include <cuda/std/__cccl/epilogue.h>
|
||||
|
||||
#endif // _CUDA___UTILITY_BASIC_ANY_SEMIREGULAR_H
|
||||
@@ -0,0 +1,79 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of libcu++, the C++ Standard Library for your entire system,
|
||||
// under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
// SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef _CUDA___UTILITY_BASIC_ANY_STORAGE_H
|
||||
#define _CUDA___UTILITY_BASIC_ANY_STORAGE_H
|
||||
|
||||
#include <cuda/std/detail/__config>
|
||||
|
||||
#if defined(_CCCL_IMPLICIT_SYSTEM_HEADER_GCC)
|
||||
# pragma GCC system_header
|
||||
#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_CLANG)
|
||||
# pragma clang system_header
|
||||
#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_MSVC)
|
||||
# pragma system_header
|
||||
#endif // no system header
|
||||
|
||||
#include <cuda/__utility/__basic_any/basic_any_fwd.h>
|
||||
#include <cuda/std/__algorithm/max.h>
|
||||
#include <cuda/std/__tuple_dir/ignore.h>
|
||||
#include <cuda/std/__type_traits/is_nothrow_move_constructible.h>
|
||||
#include <cuda/std/__type_traits/type_identity.h>
|
||||
#include <cuda/std/__utility/swap.h>
|
||||
|
||||
#include <cuda/std/__cccl/prologue.h>
|
||||
|
||||
_CCCL_BEGIN_NAMESPACE_CUDA
|
||||
|
||||
[[nodiscard]] _CCCL_HOST_DEVICE_API inline constexpr auto __buffer_size(size_t __size) -> size_t
|
||||
{
|
||||
//! round up to the nearest multiple of `__word`, which is the size of a
|
||||
//! void*.
|
||||
return ((__size ? (::cuda::std::max) (__size, sizeof(void*)) : __default_small_object_size) + __word - 1) / __word
|
||||
* __word;
|
||||
}
|
||||
|
||||
[[nodiscard]] _CCCL_HOST_DEVICE_API inline constexpr auto __buffer_align(size_t __align) -> size_t
|
||||
{
|
||||
//! need to be able to store a void* in the buffer.
|
||||
return __align ? (::cuda::std::max) (__align, alignof(void*)) : __default_small_object_align;
|
||||
}
|
||||
|
||||
template <class _Tp, bool _RequiresMovable = true>
|
||||
[[nodiscard]] _CCCL_HOST_DEVICE_API inline constexpr auto __is_small(size_t __size, size_t __align) noexcept -> bool
|
||||
{
|
||||
return (sizeof(_Tp) <= __size) && (__align % alignof(_Tp) == 0)
|
||||
&& (!_RequiresMovable || ::cuda::std::is_nothrow_move_constructible_v<_Tp>);
|
||||
}
|
||||
|
||||
_CCCL_HOST_DEVICE_API inline void __swap_ptr_ptr(void* __lhs, void* __rhs) noexcept
|
||||
{
|
||||
::cuda::std::swap(*static_cast<void**>(__lhs), *static_cast<void**>(__rhs));
|
||||
}
|
||||
|
||||
template <class _Tp,
|
||||
class _Up,
|
||||
class _Vp = decltype(true ? ::cuda::std::type_identity_t<_Tp*>() : ::cuda::std::type_identity_t<_Up*>())>
|
||||
[[nodiscard]] _CCCL_NODEBUG_API auto __ptr_eq(_Tp* __lhs, _Up* __rhs) noexcept -> bool
|
||||
{
|
||||
return static_cast<_Vp>(__lhs) == static_cast<_Vp>(__rhs);
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
_CCCL_NODEBUG_API constexpr auto __ptr_eq(::cuda::std::__ignore_t, ::cuda::std::__ignore_t) noexcept -> bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
_CCCL_END_NAMESPACE_CUDA
|
||||
|
||||
#include <cuda/std/__cccl/epilogue.h>
|
||||
|
||||
#endif // _CUDA___UTILITY_BASIC_ANY_STORAGE_H
|
||||
@@ -0,0 +1,58 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of libcu++, the C++ Standard Library for your entire system,
|
||||
// under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
// SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef _CUDA___UTILITY_BASIC_ANY_TAGGED_PTR_H
|
||||
#define _CUDA___UTILITY_BASIC_ANY_TAGGED_PTR_H
|
||||
|
||||
#include <cuda/std/detail/__config>
|
||||
|
||||
#if defined(_CCCL_IMPLICIT_SYSTEM_HEADER_GCC)
|
||||
# pragma GCC system_header
|
||||
#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_CLANG)
|
||||
# pragma clang system_header
|
||||
#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_MSVC)
|
||||
# pragma system_header
|
||||
#endif // no system header
|
||||
|
||||
#include <cuda/__utility/__basic_any/basic_any_fwd.h>
|
||||
|
||||
#include <cuda/std/__cccl/prologue.h>
|
||||
|
||||
_CCCL_BEGIN_NAMESPACE_CUDA
|
||||
|
||||
template <class _Ptr>
|
||||
struct __tagged_ptr;
|
||||
|
||||
template <class _Tp>
|
||||
struct __tagged_ptr<_Tp*>
|
||||
{
|
||||
_CCCL_HOST_DEVICE_API void __set(_Tp* __pv, bool __flag) noexcept
|
||||
{
|
||||
__ptr_ = reinterpret_cast<uintptr_t>(__pv) | uintptr_t(__flag);
|
||||
}
|
||||
|
||||
[[nodiscard]] _CCCL_HOST_DEVICE_API auto __get() const noexcept -> _Tp*
|
||||
{
|
||||
return reinterpret_cast<_Tp*>(__ptr_ & ~uintptr_t(1));
|
||||
}
|
||||
|
||||
[[nodiscard]] _CCCL_HOST_DEVICE_API auto __flag() const noexcept -> bool
|
||||
{
|
||||
return static_cast<bool>(__ptr_ & uintptr_t(1));
|
||||
}
|
||||
|
||||
uintptr_t __ptr_ = 0;
|
||||
};
|
||||
|
||||
_CCCL_END_NAMESPACE_CUDA
|
||||
|
||||
#include <cuda/std/__cccl/epilogue.h>
|
||||
|
||||
#endif // _CUDA___UTILITY_BASIC_ANY_TAGGED_PTR_H
|
||||
@@ -0,0 +1,162 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of libcu++, the C++ Standard Library for your entire system,
|
||||
// under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
// SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef _CUDA___UTILITY_BASIC_ANY_VIRTCALL_H
|
||||
#define _CUDA___UTILITY_BASIC_ANY_VIRTCALL_H
|
||||
|
||||
#include <cuda/std/detail/__config>
|
||||
|
||||
#if defined(_CCCL_IMPLICIT_SYSTEM_HEADER_GCC)
|
||||
# pragma GCC system_header
|
||||
#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_CLANG)
|
||||
# pragma clang system_header
|
||||
#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_MSVC)
|
||||
# pragma system_header
|
||||
#endif // no system header
|
||||
|
||||
#include <cuda/__utility/__basic_any/access.h>
|
||||
#include <cuda/__utility/__basic_any/basic_any_from.h>
|
||||
#include <cuda/__utility/__basic_any/basic_any_fwd.h>
|
||||
#include <cuda/__utility/__basic_any/interfaces.h>
|
||||
#include <cuda/__utility/__basic_any/virtual_functions.h>
|
||||
#include <cuda/std/__concepts/concept_macros.h>
|
||||
#include <cuda/std/__type_traits/is_callable.h>
|
||||
|
||||
#include <cuda/std/__cccl/prologue.h>
|
||||
|
||||
_CCCL_DIAG_PUSH
|
||||
_CCCL_DIAG_SUPPRESS_CLANG("-Wunused-local-typedefs")
|
||||
|
||||
_CCCL_BEGIN_NAMESPACE_CUDA
|
||||
|
||||
//!
|
||||
//! __virtuals_map
|
||||
//!
|
||||
|
||||
//! The virtuals map is an extra convenience for interface authors. To make a
|
||||
//! virtual function call, the user must provide the member function pointer
|
||||
//! corresponding to the virtual, as in:
|
||||
//!
|
||||
//! \code{.cpp}
|
||||
//! template <class...>
|
||||
//! struct ifoo {
|
||||
//! void meow(auto... args) {
|
||||
//! // dispatch to the &ifoo<>::meow virtual function
|
||||
//! // NB: the `<>` after `ifoo` is significant!
|
||||
//! __virtcall<&ifoo<>::meow>(this, args...);
|
||||
//! // ^^
|
||||
//! }
|
||||
//! ...
|
||||
//! };
|
||||
//! \endcode
|
||||
//!
|
||||
//! When taking the address of the member, it is very easy to forget the `<>`
|
||||
//! after the interface name, which would result in a compilation error --
|
||||
//! except for the virtuals map, which substitutes the correct member function
|
||||
//! pointer for the user so they don't have to think about it.
|
||||
template <auto _Mbr, auto _BoundMbr>
|
||||
struct __virtuals_map_element
|
||||
{
|
||||
// map ifoo<>::meow to itself
|
||||
_CCCL_HOST_DEVICE_API auto operator()(__ctag<_Mbr>) const -> __virtual_fn<_Mbr>;
|
||||
|
||||
// map ifoo<_Super>::meow to ifoo<>::meow
|
||||
_CCCL_HOST_DEVICE_API auto operator()(__ctag<_BoundMbr>) const -> __virtual_fn<_Mbr>;
|
||||
};
|
||||
|
||||
template <class, class>
|
||||
struct __virtuals_map;
|
||||
|
||||
template <class _Interface, class... _Mbrs, class _BoundInterface, auto... _BoundMbrs>
|
||||
struct __virtuals_map<__overrides_list<_Interface, _Mbrs...>, __overrides_for<_BoundInterface, _BoundMbrs...>>
|
||||
: __virtuals_map_element<_Mbrs::value, _BoundMbrs>...
|
||||
{
|
||||
using __virtuals_map_element<_Mbrs::value, _BoundMbrs>::operator()...;
|
||||
};
|
||||
|
||||
template <class _Interface, class _Super>
|
||||
using __virtuals_map_for _CCCL_NODEBUG_ALIAS =
|
||||
__virtuals_map<__overrides_for_t<_Interface>, __overrides_for_t<__rebind_interface<_Interface, _Super>>>;
|
||||
|
||||
template <auto _Mbr, class _Interface, class _Super>
|
||||
extern ::cuda::std::__call_result_t<__virtuals_map_for<_Interface, _Super>, __ctag<_Mbr>> __virtual_fn_for_v;
|
||||
|
||||
// This alias indirects through the above variable template to cache the result
|
||||
// of the virtuals map lookup.
|
||||
template <auto _Mbr, class _Interface, class _Super>
|
||||
using __virtual_fn_for _CCCL_NODEBUG_ALIAS = decltype(__virtual_fn_for_v<_Mbr, _Interface, _Super>);
|
||||
|
||||
//!
|
||||
//! __virtcall
|
||||
//!
|
||||
|
||||
// If the interface is __ireference<MyInterface const>, then calls to non-const
|
||||
// member functions are not allowed.
|
||||
template <auto, class... _Interface>
|
||||
inline constexpr bool __valid_virtcall = sizeof...(_Interface) == 1;
|
||||
|
||||
template <auto _Mbr, class _Interface>
|
||||
inline constexpr bool __valid_virtcall<_Mbr, __ireference<_Interface const>> = __virtual_fn<_Mbr>::__const_fn;
|
||||
|
||||
template <auto _Mbr, class _Interface, class _Super, class _Self, class... _Args>
|
||||
_CCCL_HOST_DEVICE_API auto __virtcall(_Self* __self, _Args&&... __args) //
|
||||
noexcept(__virtual_fn<_Mbr>::__nothrow_fn) //
|
||||
-> typename __virtual_fn<_Mbr>::__result_t
|
||||
{
|
||||
auto* __vptr = __basic_any_access::__get_vptr(*__self)->__query_interface(_Interface());
|
||||
auto* __obj = __basic_any_access::__get_optr(*__self);
|
||||
// map the member function pointer to the correct one if necessary
|
||||
using __virtual_fn_t = __virtual_fn_for<_Mbr, _Interface, _Super>;
|
||||
return __vptr->__virtual_fn_t::__fn_(__obj, static_cast<_Args&&>(__args)...);
|
||||
}
|
||||
|
||||
_CCCL_TEMPLATE(auto _Mbr, template <class...> class _Interface, class _Super, class... _Args)
|
||||
_CCCL_REQUIRES(__valid_virtcall<_Mbr, _Super>)
|
||||
_CCCL_NODEBUG_API auto __virtcall(_Interface<_Super>* __self, _Args&&... __args) //
|
||||
noexcept(__virtual_fn<_Mbr>::__nothrow_fn) //
|
||||
-> typename __virtual_fn<_Mbr>::__result_t
|
||||
{
|
||||
return ::cuda::__virtcall<_Mbr, _Interface<>, _Super>(
|
||||
::cuda::__basic_any_from(__self), static_cast<_Args&&>(__args)...);
|
||||
}
|
||||
|
||||
_CCCL_TEMPLATE(auto _Mbr, template <class...> class _Interface, class _Super, class... _Args)
|
||||
_CCCL_REQUIRES(__valid_virtcall<_Mbr, _Super>)
|
||||
_CCCL_NODEBUG_API auto __virtcall(_Interface<_Super> const* __self, _Args&&... __args) //
|
||||
noexcept(__virtual_fn<_Mbr>::__nothrow_fn) //
|
||||
-> typename __virtual_fn<_Mbr>::__result_t
|
||||
{
|
||||
return ::cuda::__virtcall<_Mbr, _Interface<>, _Super>(
|
||||
::cuda::__basic_any_from(__self), static_cast<_Args&&>(__args)...);
|
||||
}
|
||||
|
||||
_CCCL_TEMPLATE(auto _Mbr, template <class...> class _Interface, class... _Super, class... _Args)
|
||||
_CCCL_REQUIRES((!__valid_virtcall<_Mbr, _Super...>) )
|
||||
_CCCL_NODEBUG_API auto __virtcall(_Interface<_Super...> const*, _Args&&...) //
|
||||
noexcept(__virtual_fn<_Mbr>::__nothrow_fn) //
|
||||
-> typename __virtual_fn<_Mbr>::__result_t
|
||||
{
|
||||
constexpr bool __const_correct_virtcall = __valid_virtcall<_Mbr, _Super...> || sizeof...(_Super) == 0;
|
||||
// If this static assert fires, then you have called a non-const member
|
||||
// function on a `__basic_any<I const&>`. This would violate const-correctness.
|
||||
static_assert(__const_correct_virtcall, "This function call is not const correct.");
|
||||
// This overload can also be selected when called from the thunks of
|
||||
// unspecialized interfaces. Those thunks should never be called, but they
|
||||
// must exist to satisfy the compiler.
|
||||
_CCCL_UNREACHABLE();
|
||||
}
|
||||
|
||||
_CCCL_END_NAMESPACE_CUDA
|
||||
|
||||
_CCCL_DIAG_POP
|
||||
|
||||
#include <cuda/std/__cccl/epilogue.h>
|
||||
|
||||
#endif // _CUDA___UTILITY_BASIC_ANY_VIRTCALL_H
|
||||
@@ -0,0 +1,195 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of libcu++, the C++ Standard Library for your entire system,
|
||||
// under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
// SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef _CUDA___UTILITY_BASIC_ANY_VIRUAL_FUNCTIONS_H
|
||||
#define _CUDA___UTILITY_BASIC_ANY_VIRUAL_FUNCTIONS_H
|
||||
|
||||
#include <cuda/std/detail/__config>
|
||||
|
||||
#if defined(_CCCL_IMPLICIT_SYSTEM_HEADER_GCC)
|
||||
# pragma GCC system_header
|
||||
#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_CLANG)
|
||||
# pragma clang system_header
|
||||
#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_MSVC)
|
||||
# pragma system_header
|
||||
#endif // no system header
|
||||
|
||||
#include <cuda/__utility/__basic_any/basic_any_fwd.h>
|
||||
#include <cuda/std/__algorithm/max.h>
|
||||
#include <cuda/std/__type_traits/integral_constant.h>
|
||||
#include <cuda/std/__type_traits/is_base_of.h>
|
||||
#include <cuda/std/__type_traits/is_member_function_pointer.h>
|
||||
#include <cuda/std/__type_traits/is_nothrow_move_constructible.h>
|
||||
#include <cuda/std/__type_traits/is_pointer.h>
|
||||
#include <cuda/std/__type_traits/is_same.h>
|
||||
#include <cuda/std/__type_traits/maybe_const.h>
|
||||
#include <cuda/std/__type_traits/remove_pointer.h>
|
||||
#include <cuda/std/__type_traits/type_identity.h>
|
||||
#include <cuda/std/__type_traits/type_list.h>
|
||||
#include <cuda/std/__utility/swap.h>
|
||||
#include <cuda/std/__utility/typeid.h>
|
||||
|
||||
#include <cuda/std/__cccl/prologue.h>
|
||||
|
||||
_CCCL_BEGIN_NAMESPACE_CUDA
|
||||
|
||||
//!
|
||||
//! __override_tag
|
||||
//!
|
||||
template <class _Tp, auto _Override>
|
||||
struct __override_tag_;
|
||||
|
||||
template <class _Tp, auto _Override>
|
||||
using __override_tag _CCCL_NODEBUG_ALIAS = __override_tag_<_Tp, _Override>*;
|
||||
|
||||
_CCCL_DIAG_PUSH
|
||||
_CCCL_DIAG_SUPPRESS_GCC("-Wstrict-aliasing")
|
||||
|
||||
template <class _Fn, class _Cp>
|
||||
_CCCL_HOST_DEVICE_API auto __class_of_(_Fn _Cp::*) -> _Cp;
|
||||
|
||||
template <class _Fn>
|
||||
using __class_of _CCCL_NODEBUG_ALIAS = decltype(::cuda::__class_of_(_Fn()));
|
||||
|
||||
//! We use a C-style cast instead of a static_cast because a C-style cast will
|
||||
//! ignore accessibility, letting us cast to a private base class.
|
||||
template <class _DstPtr, class _Src>
|
||||
_CCCL_NODEBUG_API auto __c_style_cast(_Src* __ptr) noexcept -> _DstPtr
|
||||
{
|
||||
static_assert(::cuda::std::is_pointer_v<_DstPtr>);
|
||||
static_assert(::cuda::std::is_base_of_v<::cuda::std::remove_pointer_t<_DstPtr>, _Src>,
|
||||
"invalid C-style cast detected");
|
||||
return (_DstPtr) __ptr; // NOLINT(cppcoreguidelines-pro-type-cstyle-cast)
|
||||
}
|
||||
|
||||
// Helper function to not use a function pointer as a template parameter, which breaks MSVC in some cases.
|
||||
template <class _Tp, class _FnType, class _Ret, bool _IsConst, bool _IsNothrow, class... _Args>
|
||||
[[nodiscard]] _CCCL_HOST_DEVICE_API auto __override_fn_dispatch_impl(
|
||||
[[maybe_unused]] _FnType __fn,
|
||||
[[maybe_unused]] ::cuda::std::__maybe_const<_IsConst, void>* __pv,
|
||||
[[maybe_unused]] _Args... __args) noexcept(_IsNothrow) -> _Ret
|
||||
{
|
||||
using __value_type _CCCL_NODEBUG_ALIAS = ::cuda::std::__maybe_const<_IsConst, _Tp>;
|
||||
|
||||
if constexpr (::cuda::std::is_same_v<_Tp, void>)
|
||||
{
|
||||
// This instantiation is created only during the computation of the vtable
|
||||
// type. It is never actually called.
|
||||
_CCCL_UNREACHABLE();
|
||||
}
|
||||
else if constexpr (::cuda::std::is_member_function_pointer_v<_FnType>)
|
||||
{
|
||||
// _Fn may be a pointer to a member function of a private base of _Tp. So
|
||||
// after static_cast-ing to _Tp*, we need to use a C-style cast to get a
|
||||
// pointer to the correct base class.
|
||||
using __class_type = ::cuda::std::__maybe_const<_IsConst, __class_of<_FnType>>;
|
||||
__class_type& __obj = *::cuda::__c_style_cast<__class_type*>(static_cast<__value_type*>(__pv));
|
||||
return (__obj.*__fn)(static_cast<_Args&&>(__args)...);
|
||||
}
|
||||
else
|
||||
{
|
||||
__value_type& __obj = *static_cast<__value_type*>(__pv);
|
||||
return (*__fn)(__obj, static_cast<_Args&&>(__args)...);
|
||||
}
|
||||
}
|
||||
|
||||
template <class _Tp, auto _Fn, class _Ret, bool _IsConst, bool _IsNothrow, class... _Args>
|
||||
[[nodiscard]] _CCCL_HOST_DEVICE_API auto
|
||||
__override_fn_([[maybe_unused]] ::cuda::std::__maybe_const<_IsConst, void>* __pv,
|
||||
[[maybe_unused]] _Args... __args) noexcept(_IsNothrow) -> _Ret
|
||||
{
|
||||
return __override_fn_dispatch_impl<_Tp, decltype(_Fn), _Ret, _IsConst, _IsNothrow, _Args...>(
|
||||
_Fn, __pv, static_cast<_Args&&>(__args)...);
|
||||
}
|
||||
|
||||
_CCCL_DIAG_POP
|
||||
|
||||
template <class _Fn, class _Tp = void, auto _Override = 0>
|
||||
extern ::cuda::std::__undefined<_Fn> __virtual_override_fn;
|
||||
|
||||
template <class _Tp, auto _Override, class _Ret, class _Cp, class... _Args>
|
||||
inline constexpr ::cuda::std::type_identity_t<_Ret (*)(void*, _Args...)> //
|
||||
__virtual_override_fn<_Ret (*)(_Cp&, _Args...), _Tp, _Override> = //
|
||||
&__override_fn_<_Tp, _Override, _Ret, false, false, _Args...>;
|
||||
|
||||
template <class _Tp, auto _Override, class _Ret, class _Cp, class... _Args>
|
||||
inline constexpr ::cuda::std::type_identity_t<_Ret (*)(void const*, _Args...)>
|
||||
__virtual_override_fn<_Ret (*)(_Cp const&, _Args...), _Tp, _Override> =
|
||||
&__override_fn_<_Tp, _Override, _Ret, true, false, _Args...>;
|
||||
|
||||
template <class _Tp, auto _Override, class _Ret, class _Cp, class... _Args>
|
||||
inline constexpr ::cuda::std::type_identity_t<_Ret (*)(void*, _Args...) noexcept>
|
||||
__virtual_override_fn<_Ret (*)(_Cp&, _Args...) noexcept, _Tp, _Override> =
|
||||
&__override_fn_<_Tp, _Override, _Ret, false, true, _Args...>;
|
||||
|
||||
template <class _Tp, auto _Override, class _Ret, class _Cp, class... _Args>
|
||||
inline constexpr ::cuda::std::type_identity_t<_Ret (*)(void const*, _Args...) noexcept>
|
||||
__virtual_override_fn<_Ret (*)(_Cp const&, _Args...) noexcept, _Tp, _Override> =
|
||||
&__override_fn_<_Tp, _Override, _Ret, true, true, _Args...>;
|
||||
|
||||
// TODO: Add support for member functions with reference qualifiers.
|
||||
|
||||
template <class _Tp, auto _Override, class _Ret, class _Cp, class... _Args>
|
||||
inline constexpr ::cuda::std::type_identity_t<_Ret (*)(void*, _Args...)> //
|
||||
__virtual_override_fn<_Ret (_Cp::*)(_Args...), _Tp, _Override> = //
|
||||
&__override_fn_<_Tp, _Override, _Ret, false, false, _Args...>;
|
||||
|
||||
template <class _Tp, auto _Override, class _Ret, class _Cp, class... _Args>
|
||||
inline constexpr ::cuda::std::type_identity_t<_Ret (*)(void const*, _Args...)> //
|
||||
__virtual_override_fn<_Ret (_Cp::*)(_Args...) const, _Tp, _Override> =
|
||||
&__override_fn_<_Tp, _Override, _Ret, true, false, _Args...>;
|
||||
|
||||
template <class _Tp, auto _Override, class _Ret, class _Cp, class... _Args>
|
||||
inline constexpr ::cuda::std::type_identity_t<_Ret (*)(void*, _Args...) noexcept>
|
||||
__virtual_override_fn<_Ret (_Cp::*)(_Args...) noexcept, _Tp, _Override> =
|
||||
&__override_fn_<_Tp, _Override, _Ret, false, true, _Args...>;
|
||||
|
||||
template <class _Tp, auto _Override, class _Ret, class _Cp, class... _Args>
|
||||
inline constexpr ::cuda::std::type_identity_t<_Ret (*)(void const*, _Args...) noexcept>
|
||||
__virtual_override_fn<_Ret (_Cp::*)(_Args...) const noexcept, _Tp, _Override> =
|
||||
&__override_fn_<_Tp, _Override, _Ret, true, true, _Args...>;
|
||||
|
||||
template <class _Ret, class... _Args>
|
||||
_CCCL_HOST_DEVICE_API auto __get_virtual_result(_Ret (*)(_Args...)) -> _Ret;
|
||||
|
||||
template <class _Ret, class... _Args>
|
||||
_CCCL_HOST_DEVICE_API auto __get_virtual_result(_Ret (*)(_Args...) noexcept) noexcept -> _Ret;
|
||||
|
||||
template <class _Ret, class... _Args>
|
||||
_CCCL_HOST_DEVICE_API auto __is_virtual_const(_Ret (*)(void*, _Args...)) -> ::cuda::std::false_type;
|
||||
|
||||
template <class _Ret, class... _Args>
|
||||
_CCCL_HOST_DEVICE_API auto __is_virtual_const(_Ret (*)(void const*, _Args...)) -> ::cuda::std::true_type;
|
||||
|
||||
//!
|
||||
//! __virtual_fn
|
||||
//!
|
||||
template <auto _Fn>
|
||||
struct __virtual_fn
|
||||
{
|
||||
using __function_t _CCCL_NODEBUG_ALIAS = decltype(__virtual_override_fn<decltype(_Fn)>);
|
||||
using __result_t _CCCL_NODEBUG_ALIAS = decltype(__get_virtual_result(__function_t{}));
|
||||
|
||||
static constexpr bool __const_fn = decltype(::cuda::__is_virtual_const(__function_t{}))::value;
|
||||
static constexpr bool __nothrow_fn = noexcept(::cuda::__get_virtual_result(__function_t{}));
|
||||
|
||||
template <class _Tp, auto _Override>
|
||||
_CCCL_HOST_DEVICE_API constexpr __virtual_fn(__override_tag<_Tp, _Override>) noexcept
|
||||
: __fn_(__virtual_override_fn<decltype(_Fn), _Tp, _Override>)
|
||||
{}
|
||||
|
||||
__function_t __fn_;
|
||||
};
|
||||
|
||||
_CCCL_END_NAMESPACE_CUDA
|
||||
|
||||
#include <cuda/std/__cccl/epilogue.h>
|
||||
|
||||
#endif // _CUDA___UTILITY_BASIC_ANY_VIRUAL_FUNCTIONS_H
|
||||
@@ -0,0 +1,82 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of libcu++, the C++ Standard Library for your entire system,
|
||||
// under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
// SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef _CUDA___UTILITY_BASIC_ANY_VIRTUAL_PTRS_H
|
||||
#define _CUDA___UTILITY_BASIC_ANY_VIRTUAL_PTRS_H
|
||||
|
||||
#include <cuda/std/detail/__config>
|
||||
|
||||
#if defined(_CCCL_IMPLICIT_SYSTEM_HEADER_GCC)
|
||||
# pragma GCC system_header
|
||||
#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_CLANG)
|
||||
# pragma clang system_header
|
||||
#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_MSVC)
|
||||
# pragma system_header
|
||||
#endif // no system header
|
||||
|
||||
#include <cuda/__utility/__basic_any/basic_any_fwd.h>
|
||||
#include <cuda/__utility/__basic_any/interfaces.h>
|
||||
#include <cuda/std/__exception/terminate.h>
|
||||
#include <cuda/std/__utility/typeid.h>
|
||||
|
||||
#include <cuda/std/__cccl/prologue.h>
|
||||
|
||||
_CCCL_BEGIN_NAMESPACE_CUDA
|
||||
|
||||
struct __base_vptr
|
||||
{
|
||||
__base_vptr() = default;
|
||||
|
||||
_CCCL_NODEBUG_API constexpr __base_vptr(__rtti_base const* __vptr) noexcept
|
||||
: __vptr_(__vptr)
|
||||
{}
|
||||
|
||||
template <class _VTable>
|
||||
[[nodiscard]] _CCCL_NODEBUG_API explicit constexpr operator _VTable const*() const noexcept
|
||||
{
|
||||
auto const* __vptr = static_cast<_VTable const*>(__vptr_);
|
||||
_CCCL_ASSERT(_CCCL_TYPEID(_VTable) == *__vptr->__typeid_, "bad vtable cast detected");
|
||||
return __vptr;
|
||||
}
|
||||
|
||||
[[nodiscard]] _CCCL_NODEBUG_API explicit constexpr operator bool() const noexcept
|
||||
{
|
||||
return __vptr_ != nullptr;
|
||||
}
|
||||
|
||||
[[nodiscard]] _CCCL_NODEBUG_API constexpr auto operator->() const noexcept -> __rtti_base const*
|
||||
{
|
||||
return __vptr_;
|
||||
}
|
||||
|
||||
#if !defined(_CCCL_NO_THREE_WAY_COMPARISON)
|
||||
bool operator==(__base_vptr const& __other) const noexcept = default;
|
||||
#else // ^^^ !_CCCL_NO_THREE_WAY_COMPARISON ^^^ / vvv _CCCL_NO_THREE_WAY_COMPARISON vvv
|
||||
[[nodiscard]] _CCCL_HOST_DEVICE_API friend constexpr auto operator==(__base_vptr __lhs, __base_vptr __rhs) noexcept
|
||||
-> bool
|
||||
{
|
||||
return __lhs.__vptr_ == __rhs.__vptr_;
|
||||
}
|
||||
|
||||
[[nodiscard]] _CCCL_HOST_DEVICE_API friend constexpr auto operator!=(__base_vptr __lhs, __base_vptr __rhs) noexcept
|
||||
-> bool
|
||||
{
|
||||
return !(__lhs == __rhs);
|
||||
}
|
||||
#endif // _CCCL_NO_THREE_WAY_COMPARISON
|
||||
|
||||
__rtti_base const* __vptr_{};
|
||||
};
|
||||
|
||||
_CCCL_END_NAMESPACE_CUDA
|
||||
|
||||
#include <cuda/std/__cccl/epilogue.h>
|
||||
|
||||
#endif // _CUDA___UTILITY_BASIC_ANY_VIRTUAL_PTRS_H
|
||||
@@ -0,0 +1,157 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of libcu++, the C++ Standard Library for your entire system,
|
||||
// under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
// SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef _CUDA___UTILITY_BASIC_ANY_VIRTUAL_TABLES_H
|
||||
#define _CUDA___UTILITY_BASIC_ANY_VIRTUAL_TABLES_H
|
||||
|
||||
#include <cuda/std/detail/__config>
|
||||
|
||||
#if defined(_CCCL_IMPLICIT_SYSTEM_HEADER_GCC)
|
||||
# pragma GCC system_header
|
||||
#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_CLANG)
|
||||
# pragma clang system_header
|
||||
#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_MSVC)
|
||||
# pragma system_header
|
||||
#endif // no system header
|
||||
|
||||
#include <cuda/__utility/__basic_any/basic_any_fwd.h>
|
||||
#include <cuda/__utility/__basic_any/interfaces.h>
|
||||
#include <cuda/__utility/__basic_any/rtti.h>
|
||||
#include <cuda/__utility/__basic_any/virtual_functions.h>
|
||||
#include <cuda/__utility/__basic_any/virtual_ptrs.h>
|
||||
#include <cuda/std/__exception/terminate.h>
|
||||
#include <cuda/std/__utility/typeid.h>
|
||||
|
||||
#include <nv/target>
|
||||
|
||||
#include <cuda/std/__cccl/prologue.h>
|
||||
|
||||
_CCCL_BEGIN_NAMESPACE_CUDA
|
||||
|
||||
template <class _Interface>
|
||||
using __vtable_for _CCCL_NODEBUG_ALIAS = typename __overrides_for_t<_Interface>::__vtable;
|
||||
|
||||
//!
|
||||
//! __basic_vtable
|
||||
//!
|
||||
template <class _Interface, auto... _Mbrs>
|
||||
struct _CCCL_DECLSPEC_EMPTY_BASES _CCCL_TYPE_VISIBILITY_DEFAULT __basic_vtable
|
||||
: __rtti_base
|
||||
, __virtual_fn<_Mbrs>...
|
||||
{
|
||||
using interface _CCCL_NODEBUG_ALIAS = _Interface;
|
||||
static constexpr size_t __cbases = ::cuda::std::__type_list_size<__unique_interfaces<interface>>::value;
|
||||
|
||||
template <class _VPtr, class _Tp, class... _OtherMembers, class... _Interfaces>
|
||||
_CCCL_HOST_DEVICE_API constexpr __basic_vtable(
|
||||
_VPtr __vptr, __overrides_list<_Tp, _OtherMembers...>, __tag<_Interfaces...>) noexcept
|
||||
: __rtti_base{__vtable_kind::__normal, __cbases, _CCCL_TYPEID(__basic_vtable)}
|
||||
, __virtual_fn<_Mbrs>{__override_tag<_Tp, _OtherMembers::value>{}}...
|
||||
, __vptr_map_{__base_vptr{__vptr->__query_interface(_Interfaces())}...}
|
||||
{}
|
||||
|
||||
template <class _Tp, class _VPtr>
|
||||
_CCCL_HOST_DEVICE_API constexpr __basic_vtable(__tag<_Tp>, _VPtr __vptr) noexcept
|
||||
: __basic_vtable{__vptr,
|
||||
__overrides_for_t<interface, _Tp>(),
|
||||
__unique_interfaces<interface, ::cuda::std::__type_quote<__tag>>()}
|
||||
{}
|
||||
|
||||
[[nodiscard]] _CCCL_HOST_DEVICE_API auto __query_interface(interface) const noexcept -> __vptr_for<interface>
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
template <class... _Others>
|
||||
[[nodiscard]] _CCCL_HOST_DEVICE_API auto __query_interface(__iset_<_Others...>) const noexcept
|
||||
-> __vptr_for<__iset_<_Others...>>
|
||||
{
|
||||
using __remainder _CCCL_NODEBUG_ALIAS =
|
||||
::cuda::std::__type_list_size<::cuda::std::__type_find<__unique_interfaces<interface>, __iset_<_Others...>>>;
|
||||
constexpr size_t __index = __cbases - __remainder::value;
|
||||
if constexpr (__index < __cbases)
|
||||
{
|
||||
// `_Interface` extends __iset_<_Others...> exactly. We can return an actual
|
||||
// vtable pointer.
|
||||
return static_cast<__vtable_for<__iset_<_Others...>> const*>(__vptr_map_[__index]);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Otherwise, we have to return a subset vtable pointer, which does
|
||||
// dynamic interface lookup.
|
||||
return static_cast<__vptr_for<__iset_<_Others...>>>(__query_interface(__iunknown()));
|
||||
}
|
||||
}
|
||||
|
||||
template <class _Other>
|
||||
[[nodiscard]] _CCCL_HOST_DEVICE_API auto __query_interface(_Other) const noexcept -> __vptr_for<_Other>
|
||||
{
|
||||
constexpr size_t __index = __index_of_base<_Other, interface>::value;
|
||||
static_assert(__index < __cbases);
|
||||
return static_cast<__vptr_for<_Other>>(__vptr_map_[__index]);
|
||||
}
|
||||
|
||||
__base_vptr __vptr_map_[__cbases];
|
||||
};
|
||||
|
||||
//!
|
||||
//! __vtable implementation details
|
||||
//!
|
||||
|
||||
template <class... _Interfaces>
|
||||
struct _CCCL_DECLSPEC_EMPTY_BASES _CCCL_TYPE_VISIBILITY_DEFAULT __vtable_tuple
|
||||
: __rtti_ex<sizeof...(_Interfaces)>
|
||||
, __vtable_for<_Interfaces>...
|
||||
{
|
||||
static_assert((::cuda::std::is_class_v<_Interfaces> && ...), "expected class types");
|
||||
|
||||
template <class _Tp, class _Super>
|
||||
_CCCL_HOST_DEVICE_API constexpr __vtable_tuple(__tag<_Tp, _Super> __type) noexcept
|
||||
: __rtti_ex<sizeof...(_Interfaces)>{__type, __tag<_Interfaces...>(), this}
|
||||
#if _CCCL_COMPILER(MSVC)
|
||||
// workaround for MSVC bug
|
||||
, __overrides_for_t<_Interfaces>::__vtable{__tag<_Tp>(), this}...
|
||||
#else // ^^^ MSVC ^^^ / vvv !MSVC vvv
|
||||
, __vtable_for<_Interfaces>{__tag<_Tp>(), this}...
|
||||
#endif // !MSVC
|
||||
{
|
||||
static_assert(::cuda::std::is_class_v<_Super>, "expected a class type");
|
||||
}
|
||||
|
||||
_CCCL_TEMPLATE(class _Interface)
|
||||
_CCCL_REQUIRES(::cuda::std::__is_included_in_v<_Interface, _Interfaces...>)
|
||||
[[nodiscard]] _CCCL_HOST_DEVICE_API constexpr auto __query_interface(_Interface) const noexcept
|
||||
-> __vptr_for<_Interface>
|
||||
{
|
||||
return static_cast<__vptr_for<_Interface>>(this);
|
||||
}
|
||||
};
|
||||
|
||||
// The vtable type for type `_Interface` is a `__vtable_tuple` of `_Interface`
|
||||
// and all of its base interfaces.
|
||||
template <class _Interface>
|
||||
using __vtable _CCCL_NODEBUG_ALIAS = __unique_interfaces<_Interface, ::cuda::std::__type_quote<__vtable_tuple>>;
|
||||
|
||||
// __vtable_for_v<_Interface, _Tp> is an instance of `__vtable<_Interface>` that
|
||||
// contains the overrides for `_Tp`.
|
||||
template <class _Interface, class _Tp>
|
||||
_CCCL_GLOBAL_CONSTANT __vtable<_Interface> __vtable_for_v{__tag<_Tp, _Interface>()};
|
||||
|
||||
template <class _Interface, class _Tp>
|
||||
_CCCL_HOST_DEVICE_API constexpr __vtable<_Interface> const* __get_vtable_ptr_for() noexcept
|
||||
{
|
||||
NV_IF_ELSE_TARGET(NV_IS_HOST, (return &__vtable_for_v<_Interface, _Tp>;), (::cuda::std::terminate();))
|
||||
}
|
||||
|
||||
_CCCL_END_NAMESPACE_CUDA
|
||||
|
||||
#include <cuda/std/__cccl/epilogue.h>
|
||||
|
||||
#endif // _CUDA___UTILITY_BASIC_ANY_VIRTUAL_TABLES_H
|
||||
507
cccl_upstream/libcudacxx/include/cuda/__utility/basic_any.h
Normal file
507
cccl_upstream/libcudacxx/include/cuda/__utility/basic_any.h
Normal file
@@ -0,0 +1,507 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of libcu++, the C++ Standard Library for your entire system,
|
||||
// under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
// SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef _CUDA___UTILITY_BASIC_ANY_H
|
||||
#define _CUDA___UTILITY_BASIC_ANY_H
|
||||
|
||||
#include <cuda/std/detail/__config>
|
||||
|
||||
#if defined(_CCCL_IMPLICIT_SYSTEM_HEADER_GCC)
|
||||
# pragma GCC system_header
|
||||
#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_CLANG)
|
||||
# pragma clang system_header
|
||||
#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_MSVC)
|
||||
# pragma system_header
|
||||
#endif // no system header
|
||||
|
||||
//! \file basic_any.h
|
||||
//!
|
||||
//! \brief This file provides the implementation of the `__basic_any` class
|
||||
//! template.
|
||||
//!
|
||||
//! The `__basic_any` class template generates a type-erasing wrapper for types
|
||||
//! described by a user-provided _interface_. An interface is a class template
|
||||
//! that has member and/or friend functions that dispatch to the appropriate
|
||||
//! pseudo-virtual functions, and a nested `overrides` type alias that maps the
|
||||
//! members of a given type to the pseudo-virtuals. Objects that implement the
|
||||
//! interface will be stored in-situ in the `__basic_any` object if possible;
|
||||
//! otherwise, they will be stored on the heap.
|
||||
//!
|
||||
//! A simple interface looks like this:
|
||||
//!
|
||||
//! \code{.cpp}
|
||||
//! template <class...>
|
||||
//! struct icat : cuda::__basic_interface<icat>
|
||||
//! {
|
||||
//! void meow() const
|
||||
//! {
|
||||
//! // dispatch to the icat::meow override:
|
||||
//! cuda::__virtcall<&icat::meow>(this);
|
||||
//! }
|
||||
//!
|
||||
//! template <class Cat>
|
||||
//! using overrides = cuda::__overrides_for<Cat, &Cat::meow>;
|
||||
//! };
|
||||
//!
|
||||
//! // `any_cat` is a type-erasing wrapper that can store any object whose type
|
||||
//! // satisfies the `icat` interface.
|
||||
//! using any_cat = cuda::__basic_any<icat<>>;
|
||||
//! \endcode
|
||||
//!
|
||||
//! The `any_cat` type can now be used to store any object that implements the
|
||||
//! `icat` interface. For example:
|
||||
//!
|
||||
//! \code{.cpp}
|
||||
//! struct siamese
|
||||
//! {
|
||||
//! void meow() const
|
||||
//! {
|
||||
//! std::cout << "meow" << '\n';
|
||||
//! }
|
||||
//! };
|
||||
//!
|
||||
//! any_cat cat = siamese{};
|
||||
//! cat.meow(); // prints "meow"
|
||||
//! \endcode
|
||||
//!
|
||||
//!
|
||||
//! ## The `__basic_any` type
|
||||
//!
|
||||
//! For an interface `I`, the `__basic_any<I>` has the following member functions
|
||||
//! in addition to those provided by `I`:
|
||||
//!
|
||||
//! \code{.cpp}
|
||||
//! void swap(__basic_any<I>& other) noexcept;
|
||||
//!
|
||||
//! template <class T, class... Args>
|
||||
//! T& emplace(Args&&... args);
|
||||
//!
|
||||
//! template <class T, class U, class... Args>
|
||||
//! T& emplace(std::initializer_list<U> il, Args&&... args);
|
||||
//!
|
||||
//! bool has_value() const noexcept;
|
||||
//!
|
||||
//! void reset() noexcept;
|
||||
//!
|
||||
//! const std::type_info& type() const noexcept;
|
||||
//!
|
||||
//! const std::type_info& interface() const noexcept;
|
||||
//!
|
||||
//! bool __in_situ() const noexcept;
|
||||
//! \endcode
|
||||
//!
|
||||
//! These members behave as they do for `std::any`. The `interface()` member
|
||||
//! function returns the `std::type_info` object for the _dynamic_ interface of
|
||||
//! the stored object, which could be different from `I` if the `__basic_any`
|
||||
//! object was constructed from a `__basic_any<J>`, where `J` extends `I` (see
|
||||
//! the next section).
|
||||
//!
|
||||
//! ## Interface Extension
|
||||
//!
|
||||
//! An interface can extend other interfaces. We can make `any_cat` copyable by
|
||||
//! extending the `cuda::__icopyable` interface:
|
||||
//!
|
||||
//! \code{.cpp}
|
||||
//! template <class...>
|
||||
//! struct icat
|
||||
//! : cuda::__basic_interface<icat, cuda::__extends<cuda::__icopyable<>>>
|
||||
//! {
|
||||
//! ... as before ...
|
||||
//! \endcode
|
||||
//!
|
||||
//! The `cuda::extends` template is variadic to allow extending multiple
|
||||
//! interfaces. Interface extension works like virtual inheritance in C++; the
|
||||
//! same interface can be inherited multiple times, either directly or
|
||||
//! indirectly, without creating any ambiguity.
|
||||
//!
|
||||
//! Conversion from a "derived" `__basic_any` (e.g., `any_cat`) to a "base"
|
||||
//! `__basic_any` (e.g., `__basic_any<__icopyable<>>`) is supported.
|
||||
//!
|
||||
//! ## Pointers and References
|
||||
//!
|
||||
//! The `__basic_any` class template can hold pointers and references to objects
|
||||
//! that implement the interface. For example:
|
||||
//!
|
||||
//! \code{.cpp}
|
||||
//! // `any_cat_ptr` is a type-erasing wrapper that can store a pointer to any
|
||||
//! // (non-const) object whose type implements the `icat` interface.
|
||||
//! using any_cat_ptr = cuda::__basic_any<icat<>*>; // note the pointer type!
|
||||
//!
|
||||
//! // store a pointer to a siamese cat in a __basic_any object
|
||||
//! siamese fluffy;
|
||||
//! any_cat_ptr pcat1 = &fluffy;
|
||||
//! pcat1->meow(); // prints "meow"
|
||||
//!
|
||||
//! // a __basic_any pointer can also point to a type-erased object:
|
||||
//! any_cat cat2 = fluffy;
|
||||
//! any_cat_ptr pcat2 = &cat2;
|
||||
//! pcat2->meow(); // prints "meow"
|
||||
//! \endcode
|
||||
//!
|
||||
//! If the base interface (in this case, `icat<>`) extends `__icopyable<>` or
|
||||
//! `__imovable<>`, then you can copy or move out of a dereferenced __basic_any
|
||||
//! pointer. For example:
|
||||
//!
|
||||
//! \code{.cpp}
|
||||
//! any_cat_ptr pcat = &fluffy;
|
||||
//! any_cat copycat = *pcat; // copy from fluffy
|
||||
//! any_cat movecat = std::move(*pcat); // move from fluffy
|
||||
//! \endcode
|
||||
//!
|
||||
//! Type-erased references are supported as well. For example:
|
||||
//!
|
||||
//! \code{.cpp}
|
||||
//! // `any_cat_ref` is a type-erasing wrapper that can store a (non-owning)
|
||||
//! // reference to any (non-const) object whose type implements the `icat`
|
||||
//! // interface.
|
||||
//! using any_cat_ref = cuda::__basic_any<icat<>&>; // note the reference type!
|
||||
//!
|
||||
//! // store a non-const reference to a siamese cat in a __basic_any object:
|
||||
//! siamese fluffy;
|
||||
//! any_cat_ref rcat1 = fluffy;
|
||||
//! rcat1.meow(); // prints "meow"
|
||||
//! \endcode
|
||||
//!
|
||||
//! All the conversion sequences that are valid for pointers and references are
|
||||
//! also valid for __basic_any pointers and references. For example, a
|
||||
//! `__basic_any<I*>` can be implicitly converted to a `__basic_any<I const*>`, and
|
||||
//! a `__basic_any<IDerived&>` is implicitly convertible to a
|
||||
//! `__basic_any<IBase&>`.
|
||||
//!
|
||||
//! \warning **You cannot use `std::move` to move a value out of a __basic_any
|
||||
//! reference.** Although `any_cat value = std::move(rcat1);` will compile and
|
||||
//! looks perfectly reasonable, it will not actually move the value out of
|
||||
//! `rcat1`. Instead, it will copy the value. `std::move(rcat1)` is an rvalue
|
||||
//! reference of type `any_cat_ref`, which continues to behave like an lvalue.
|
||||
//! For this reason, __basic_any references all have a `move` member function that
|
||||
//! can be used to move the value out of the reference: `any_cat value =
|
||||
//! rcat1.move();`.
|
||||
//!
|
||||
//! ## In-Situ Storage
|
||||
//!
|
||||
//! Small objects with non-throwing move constructors can be stored in-situ in
|
||||
//! the `__basic_any` object. The size of the in-situ buffer is determined by the
|
||||
//! interface's `::size` member, which defaults to `3 * sizeof(void*)` and
|
||||
//! cannot be smaller than `sizeof(void*)`. The alignment of the in-situ buffer
|
||||
//! is determined by the interface's `::align` member, which defaults to
|
||||
//! `alignof(std::max_align_t)` and cannot be smaller than `alignof(void*)`.
|
||||
//!
|
||||
//! For convenience, the `cuda::interface` template lets you specify the size
|
||||
//! and alignment of the in-situ buffer directly:
|
||||
//!
|
||||
//! \code{.cpp}
|
||||
//! template <class...>
|
||||
//! struct icat
|
||||
//! : cuda::__basic_interface<icat,
|
||||
//! cuda::__extends<cuda::__icopyable<>>,
|
||||
//! 2 * sizeof(void*), // in-situ buffer size
|
||||
//! alignof(void*)> // in-situ buffer alignment
|
||||
//! {
|
||||
//! ... as before ...
|
||||
//! \endcode
|
||||
//!
|
||||
//! An object of type `T` will be stored in-situ in a `__basic_any<I>` object if
|
||||
//! the following conditions are met:
|
||||
//!
|
||||
//! - `I::size >= sizeof(T)`, and
|
||||
//! - `I::align % alignof(T) == 0`, and
|
||||
//! - `std::is_nothrow_move_constructible_v<T> == true`
|
||||
//!
|
||||
//! If any of these conditions are not met, the object will be stored on the
|
||||
//! heap. When such a `__basic_any` object is copied, a new `T` object will be
|
||||
//! dynamically allocated and initialized with the old object. In other words,
|
||||
//! `__basic_any` objects have value semantics regardless of how the wrapped
|
||||
//! object is stored. All `__basic_any` objects are nothrow move constructible.
|
||||
//!
|
||||
//! `__basic_any` pointer and reference types (`__basic_any<I*>` and
|
||||
//! `__basic_any<I&>`) ignore the interface's `::size` and `::align` members.
|
||||
//! Rather than an internal buffer, they store the pointer or reference
|
||||
//! directly.
|
||||
//!
|
||||
//! ## Explicit Casting
|
||||
//!
|
||||
//! TODO
|
||||
//!
|
||||
//! ## Defining An Interface
|
||||
//!
|
||||
//! An interface must be a variadic class template that inherits from the
|
||||
//! `cuda::interface` template as described above. The members of the interface
|
||||
//! stub functions, aka thunks, that both define the interface and dispatch to
|
||||
//! the type-erased pseudo-virtual overrides. You use the `cuda::__virtcall`
|
||||
//! function to dispatch to the pseudo-virtuals, using the member pointer of the
|
||||
//! thunk as a key for dispatching to the correct function.
|
||||
//!
|
||||
//! The following example shows how to define an interface that will give us the
|
||||
//! behavior of `std::function`. The interface itself needs to be parameterized
|
||||
//! by the function signature, which involves some contortions:
|
||||
//!
|
||||
//! \code{.cpp}
|
||||
//! // We use an outer template to bind the function signature to the interface.
|
||||
//! template <class Signature>
|
||||
//! struct _with_signature;
|
||||
//!
|
||||
//! template <class Ret, class... Args>
|
||||
//! struct _with_signature<Ret(Args...)>
|
||||
//! {
|
||||
//! // The actual interface is a variadic class template that inherits from
|
||||
//! // `cuda::interface` and contains the thunks.
|
||||
//! template <class...>
|
||||
//! struct _ifuntion
|
||||
//! : cuda::__basic_interface<_ifunction, cuda::__extends<cuda::__icopyable<>>>
|
||||
//! {
|
||||
//! Ret operator()(Args... args) const
|
||||
//! {
|
||||
//! return cuda::__virtcall<&_ifunction::operator()>(this, std::forward<Args>(args)...);
|
||||
//! }
|
||||
//!
|
||||
//! template <class F>
|
||||
//! using overrides = cuda::__overrides_for<F, static_cast<Ret (F::*)(Args...)
|
||||
//! const>(&F::operator())>;
|
||||
//! };
|
||||
//! };
|
||||
//!
|
||||
//! template <class Signature>
|
||||
//! using ifunction = _with_signature<Signature>::template _ifunction<>;
|
||||
//!
|
||||
//! template <class Signature>
|
||||
//! using any_function = cuda::__basic_any<ifunction<Signature>>;
|
||||
//! \endcode
|
||||
//!
|
||||
//! With the `any_function` template defined above, we can now store any callable
|
||||
//! object that has the same signature as the `Signature` template parameter.
|
||||
//!
|
||||
//! \code{.cpp}
|
||||
//! any_function<int(int, int)> fn = std::plus<int>{};
|
||||
//! assert(fn(1, 2) == 3);
|
||||
//! \endcode
|
||||
//!
|
||||
//! Within a thunk of an interface `I<>`, the `this` pointer has type
|
||||
//! `I<J>*`, where `J` is the interface used to parameterize the `__basic_any`
|
||||
//! object. For example, imagine an interface `ialley_cat` that extends `icat`.
|
||||
//! `__basic_any<ialley_cat<>>` inherits publicly from `icat<ialley_cat<>>`, which
|
||||
//! will be the type of the `this` pointer in the `icat<...>::meow()` thunk.
|
||||
//!
|
||||
//! Sometimes it is necessary to access the full `__basic_any` object from within
|
||||
//! the thunk. You can do this by passing the `this` pointer to the
|
||||
//! `cuda::__basic_any_from` function, which will return a pointer to the full
|
||||
//! `__basic_any` object; a `__basic_any<ialley_cat<>>*` in this case.
|
||||
//!
|
||||
//! ## Using Free Functions As Overrides
|
||||
//!
|
||||
//! So far, we have only seen how to bind member functions to an interface. But
|
||||
//! what if we want to bind a free function? The `cuda::__overrides_for` template can
|
||||
//! bind free functions to an interface as well. Here is an example that uses a
|
||||
//! free function, `_equal_to<T>`, to define the `__iequality_comparable`
|
||||
//! interface:
|
||||
//!
|
||||
//! \code{.cpp}
|
||||
//! template <class T>
|
||||
//! auto _equal_to(T const& lhs, std::type_info const& rhs_type, void const* rhs)
|
||||
//! -> decltype(lhs == lhs) // SFINAE out if `lhs == lhs` is ill-formed
|
||||
//! {
|
||||
//! return (rhs_type == typeid(T)) ? (lhs == *static_cast<T const*>(rhs)) : false;
|
||||
//! }
|
||||
//!
|
||||
//! template <class...>
|
||||
//! struct __iequality_comparable : cuda::__basic_interface<__iequality_comparable>
|
||||
//! {
|
||||
//! friend bool operator==(__iequality_comparable const& lhs, __iequality_comparable const& rhs)
|
||||
//! {
|
||||
//! // downcast the `rhs` object to the correct specialization of `__basic_any`:
|
||||
//! auto const& rhs_any = cuda::__basic_any_from(rhs);
|
||||
//! // get the object pointer from the `rhs` object:
|
||||
//! void const* rhs_optr = cuda::__any_cast<void const>(&rhs_any);
|
||||
//! // dispatch to the `_equal_to` override:
|
||||
//! return cuda::__virtcall<&_equal_to<__iequality_comparable>>(this, rhs_any.type(), rhs_optr);
|
||||
//! }
|
||||
//!
|
||||
//! friend bool operator!=(__iequality_comparable const& lhs, __iequality_comparable const& rhs)
|
||||
//! {
|
||||
//! return !(lhs == rhs);
|
||||
//! }
|
||||
//!
|
||||
//! template <class T>
|
||||
//! using overrides = cuda::__overrides_for<T, &_equal_to<T>>;
|
||||
//! };
|
||||
//! \endcode
|
||||
//!
|
||||
//! ## Implementation Details
|
||||
//!
|
||||
//! For an interface `I<>`, let `IBases<>...` be the (flattened, uniqued) list
|
||||
//! of interfaces that `I<>` extends, either directly or indirectly.
|
||||
//! `__basic_any<I<>>` inherits publicly from `I<I<>>` and `IBases<I<>>...`.
|
||||
//! Therefore, the members of `__basic_any<I<>>` are the thunks of `I<>`
|
||||
//! and all the interfaces that `I<>` extends.
|
||||
//!
|
||||
//! The `__basic_any<I<>>` type looks roughly like this:
|
||||
//!
|
||||
//! \code{.cpp}
|
||||
//! template <template <class...> class I>
|
||||
//! struct _CCCL_TYPE_VISIBILITY_DEFAULT __basic_any<I<>> : I<I<>>, IBases<I<>>...
|
||||
//! {
|
||||
//! // constructors, destructor, assignment operators, etc.
|
||||
//!
|
||||
//! private:
|
||||
//! // a tagged pointer to the object's vtable
|
||||
//! __tagged_ptr<__vtable<I<>> const*> __vptr_;
|
||||
//!
|
||||
//! // the object's buffer
|
||||
//! alignas(I<>::align) std::byte __buffer_[I<>::size];
|
||||
//! };
|
||||
//! \endcode
|
||||
//!
|
||||
//! The `__tagged_ptr` type wraps a pointer that uses the lowest order bit to
|
||||
//! indicate whether the buffer stores the object in-situ, or if it stores a
|
||||
//! pointer to the object on the heap.
|
||||
//!
|
||||
//! The type `__vtable<I<>>` is a struct that aggregates the vtables of `I<>`
|
||||
//! and all the interfaces that `I<>` extends. It also aggregates an "RTTI"
|
||||
//! struct that contains metadata about the object and the vtable.
|
||||
//! `__vtable<I<>>` is an alias for a type that looks like this:
|
||||
//!
|
||||
//! \code{.cpp}
|
||||
//! template <class I, class... {base-interfaces-of-I}>
|
||||
//! struct __vtable_tuple
|
||||
//! : __rtti_ex
|
||||
//! , __vtable_for<I>
|
||||
//! , __vtable_for<{base-interfaces-of-I}>...
|
||||
//! {
|
||||
//! //... constexpr constructors ...
|
||||
//!
|
||||
//! template <class Interface>
|
||||
//! __vtable_for<Interface> const* __query_interface(Interface) const noexcept;
|
||||
//! };
|
||||
//! \endcode
|
||||
//!
|
||||
//! The `__rtti_ex` struct contains a map from interface typeid's to the pointer
|
||||
//! to the vtable for that interface. This map is used for `dynamic_cast`-like
|
||||
//! functionality. `__rtti_ex` is derived from a `__rtti` class that has
|
||||
//! metadata about the type-erased object like its typeid, size, and alignment.
|
||||
//!
|
||||
//! `__vtable_for<I<>>` names a struct that contains function pointers --
|
||||
//! "overrides" -- for the pseudo-virtual functions of `I<>`. It is actually an
|
||||
//! alias for a nested struct of the `cuda::__overrides_for` template. The actual vtable
|
||||
//! struct looks like this:
|
||||
//!
|
||||
//! \code{.cpp}
|
||||
//! template <class InterfaceOrObject, auto... Mbrs>
|
||||
//! struct __overrides_for
|
||||
//! {
|
||||
//! // InterfaceOrObject is either the type of the unspecialized interface or
|
||||
//! // the type of an object that implements the interface and that is being
|
||||
//! // type-erased.
|
||||
//! struct __vtable
|
||||
//! : __rtti_base // described below
|
||||
//! , __virtual_fn<Mbrs>... // the pseudo-virtual overrides
|
||||
//! {
|
||||
//! // Within the __vtable struct, InterfaceOrObject is the type of the
|
||||
//! // unspecialized interface.
|
||||
//!
|
||||
//! // ... constexpr constructors ...
|
||||
//!
|
||||
//! template <class Interface>
|
||||
//! __vtable_for<Interface> const* __query_interface(Interface) const noexcept;
|
||||
//!
|
||||
//! // Pointers to the vtables of I's bases:
|
||||
//! using I = InterfaceOrObject;
|
||||
//! __rtti_base const* __vptr_map[{count-of-I's-bases}];
|
||||
//! };
|
||||
//! };
|
||||
//! \endcode
|
||||
//!
|
||||
//! Here is the one trick that makes the whole of `__basic_any` work:
|
||||
//! `__vtable_for<I<>>` is an alias for `I<>::overrides<I<>>::__vtable`. For the
|
||||
//! `icat` interface defined above, the `icat<>::overrides` alias looks like this:
|
||||
//!
|
||||
//! \code{.cpp}
|
||||
//! template <class T>
|
||||
//! using overrides = cuda::__overrides_for<T, &T::meow>;
|
||||
//! \endcode
|
||||
//!
|
||||
//! So `__vtable_for<icat<>>` is an alias for `cuda::__overrides_for<icat<>,
|
||||
//! &icat<>::meow>::__vtable`. `icat<>::meow` is the thunk in the `icat<>`
|
||||
//! interface.
|
||||
//!
|
||||
//! We can now describe how pseudo-virtual dispatch works. Given an object `cat`
|
||||
//! of type `__basic_any<ialley_cat<>>` that we defined above, a call of
|
||||
//! `cat.meow()` does the following:
|
||||
//!
|
||||
//! - Within the `meow` thunk, `this` has type `icat<ialley_cat<>>*`.
|
||||
//! The thunk calls `cuda::__virtcall<&icat::meow>(this)`.
|
||||
//!
|
||||
//! - `&icat::meow` is a pointer to the `icat<ialley_cat<>>::meow` thunk. The
|
||||
//! `__virtcall` infers from the `this` argument that the unspecialized
|
||||
//! interface is `icat<>`. `__virtcall` maps the `&icat<ialley_cat<>>::meow`
|
||||
//! member pointer to the `&icat<>::meow` member pointer by building a map
|
||||
//! from `icat<ialley_cat<>>::overrides<icat<ialley_cat<>>` to
|
||||
//! `icat<>::overrides<icat<>>`.
|
||||
//!
|
||||
//! - Having established that the override for `icat<>::meow` is the one that
|
||||
//! should be called, `__virtcall` calls
|
||||
//! `__basic_any_from({the-this-ptr-from-above})` to obtain a pointer to the
|
||||
//! full `__basic_any<ialley_cat<>>` object. From there, it pulls out the vtable
|
||||
//! pointer (which has type `__vtable<ialley_cat<>> const*`) and casts it to
|
||||
//! `__vtable_for<icat<>> const*`. (As described above,
|
||||
//! `__vtable<ialley_cat<>>` inherits from `__vtable_for<icat<>>`.) From
|
||||
//! there, it further casts the pointer to `__virtual_fn<&icat<>::meow>
|
||||
//! const*`, which contains the override for the `&icat<>::meow`
|
||||
//! pseudo-virtual.
|
||||
//!
|
||||
//! The `__virtual_fn` template wraps a function pointer that dispatches to the
|
||||
//! correct member of the type-erased object. It is parameterized by the member
|
||||
//! pointer of the thunk. `__virtual_fn<&icat<>::meow>` is handled by a
|
||||
//! partial specialization that looks like this:
|
||||
//!
|
||||
//! \code{.cpp}
|
||||
//! template <auto Mbr, class = decltype(Mbr)>
|
||||
//! struct __virtual_fn;
|
||||
//!
|
||||
//! template <auto Mbr, class R, class C, class... Args>
|
||||
//! struct __virtual_fn<Mbr, R (C::*)(Args...)>
|
||||
//! {
|
||||
//! using __function_t = R(*)(void*, Args...);
|
||||
//! __function_t __fn_;
|
||||
//! };
|
||||
//! \endcode
|
||||
//!
|
||||
//! When a `__basic_any<icat<>>` object is constructed from an object `fluffy` of
|
||||
//! type `siamese`, a global constexpr object of type `__vtable<icat<>>` is
|
||||
//! instantiated and initialized with `__tag<siamese>{}` (where `__tag` is an
|
||||
//! empty struct). That will cause the base sub-object `__vtable_for<icat<>>` --
|
||||
//! aka, `icat<>::overrides<icat<>>::__vtable`, aka `cuda::__overrides_for<icat<>,
|
||||
//! &icat<>::meow>::__vtable` -- to be initialized with an object of type
|
||||
//! `icat<>::overrides<siamese>`, aka `cuda::__overrides_for<siamese, &siamese::meow>`.
|
||||
//! And that causes `__virtual_fn<&icat<>::meow>` to be initialized with a
|
||||
//! pointer to a function that casts its `void*` argument to `siamese*` and
|
||||
//! dispatches to its `meow` member function. So that's how the vtable gets
|
||||
//! populated with the correct function pointers. In the `__basic_any`
|
||||
//! constructor, a pointer to that vtable is saved in its `__vptr_` member.
|
||||
|
||||
// IWYU pragma: begin_exports
|
||||
#include <cuda/__utility/__basic_any/any_cast.h>
|
||||
#include <cuda/__utility/__basic_any/basic_any_from.h>
|
||||
#include <cuda/__utility/__basic_any/basic_any_ptr.h>
|
||||
#include <cuda/__utility/__basic_any/basic_any_ref.h>
|
||||
#include <cuda/__utility/__basic_any/basic_any_value.h>
|
||||
#include <cuda/__utility/__basic_any/conversions.h>
|
||||
#include <cuda/__utility/__basic_any/dynamic_any_cast.h>
|
||||
#include <cuda/__utility/__basic_any/interfaces.h>
|
||||
#include <cuda/__utility/__basic_any/iset.h>
|
||||
#include <cuda/__utility/__basic_any/overrides.h>
|
||||
#include <cuda/__utility/__basic_any/rtti.h>
|
||||
#include <cuda/__utility/__basic_any/semiregular.h>
|
||||
#include <cuda/__utility/__basic_any/storage.h>
|
||||
#include <cuda/__utility/__basic_any/tagged_ptr.h>
|
||||
#include <cuda/__utility/__basic_any/virtcall.h>
|
||||
#include <cuda/__utility/__basic_any/virtual_functions.h>
|
||||
#include <cuda/__utility/__basic_any/virtual_tables.h>
|
||||
// IWYU pragma: end_exports
|
||||
|
||||
#endif // _CUDA___UTILITY_BASIC_ANY_H
|
||||
50
cccl_upstream/libcudacxx/include/cuda/__utility/immovable.h
Normal file
50
cccl_upstream/libcudacxx/include/cuda/__utility/immovable.h
Normal file
@@ -0,0 +1,50 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of libcu++, the C++ Standard Library for your entire system,
|
||||
// under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
// SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef _CUDA___UTILITY_IMMOVABLE_H
|
||||
#define _CUDA___UTILITY_IMMOVABLE_H
|
||||
|
||||
#include <cuda/std/detail/__config>
|
||||
|
||||
#if defined(_CCCL_IMPLICIT_SYSTEM_HEADER_GCC)
|
||||
# pragma GCC system_header
|
||||
#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_CLANG)
|
||||
# pragma clang system_header
|
||||
#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_MSVC)
|
||||
# pragma system_header
|
||||
#endif // no system header
|
||||
|
||||
#include <cuda/std/__cccl/prologue.h>
|
||||
|
||||
_CCCL_BEGIN_NAMESPACE_CUDA
|
||||
|
||||
// BUG (gcc#98995): copy elision fails when initializing a [[no_unique_address]] field
|
||||
// from a function returning an object of class type by value.
|
||||
// See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98995
|
||||
#if _CCCL_COMPILER(GCC)
|
||||
// By declaring the move constructor but not defining it, any TU that ODR-uses the move
|
||||
// constructor will cause a linker error.
|
||||
# define _CCCL_IMMOVABLE(_XP) _CCCL_API _XP(_XP&&) noexcept
|
||||
#else // ^^^ _CCCL_COMPILER(GCC) ^^^ / vvv !_CCCL_COMPILER(GCC) vvv
|
||||
# define _CCCL_IMMOVABLE(_XP) _XP(_XP&&) = delete
|
||||
#endif // !_CCCL_COMPILER(GCC)
|
||||
|
||||
// Classes can inherit from this type to become immovable.
|
||||
struct _CCCL_TYPE_VISIBILITY_DEFAULT __immovable
|
||||
{
|
||||
_CCCL_HIDE_FROM_ABI __immovable() = default;
|
||||
_CCCL_IMMOVABLE(__immovable);
|
||||
};
|
||||
|
||||
_CCCL_END_NAMESPACE_CUDA
|
||||
|
||||
#include <cuda/std/__cccl/epilogue.h>
|
||||
|
||||
#endif // _CUDA___UTILITY_IMMOVABLE_H
|
||||
65
cccl_upstream/libcudacxx/include/cuda/__utility/in_range.h
Normal file
65
cccl_upstream/libcudacxx/include/cuda/__utility/in_range.h
Normal file
@@ -0,0 +1,65 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of libcu++, the C++ Standard Library for your entire system,
|
||||
// under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
// SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef _CUDA___UTILITY_IN_RANGE_H
|
||||
#define _CUDA___UTILITY_IN_RANGE_H
|
||||
|
||||
#include <cuda/std/detail/__config>
|
||||
|
||||
#if defined(_CCCL_IMPLICIT_SYSTEM_HEADER_GCC)
|
||||
# pragma GCC system_header
|
||||
#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_CLANG)
|
||||
# pragma clang system_header
|
||||
#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_MSVC)
|
||||
# pragma system_header
|
||||
#endif // no system header
|
||||
|
||||
#include <cuda/__type_traits/is_floating_point.h>
|
||||
#include <cuda/std/__cmath/isnan.h>
|
||||
#include <cuda/std/__concepts/concept_macros.h>
|
||||
#include <cuda/std/__type_traits/conditional.h>
|
||||
#include <cuda/std/__type_traits/is_extended_floating_point.h>
|
||||
#include <cuda/std/__type_traits/is_integer.h>
|
||||
#include <cuda/std/__type_traits/is_unsigned_integer.h>
|
||||
|
||||
#include <cuda/std/__cccl/prologue.h>
|
||||
|
||||
_CCCL_BEGIN_NAMESPACE_CUDA
|
||||
|
||||
_CCCL_TEMPLATE(typename _Tp)
|
||||
_CCCL_REQUIRES(::cuda::std::__cccl_is_integer_v<_Tp> || ::cuda::std::is_floating_point_v<_Tp>
|
||||
|| ::cuda::std::__is_extended_floating_point_v<_Tp>)
|
||||
[[nodiscard]] _CCCL_API constexpr bool in_range(_Tp __v, _Tp __start, _Tp __end) noexcept
|
||||
{
|
||||
_CCCL_ASSERT(::cuda::std::isnan(__start) || ::cuda::std::isnan(__end) || __end >= __start,
|
||||
"in_range: __end must be greater than or equal to __start");
|
||||
if constexpr (::cuda::std::__cccl_is_unsigned_integer_v<_Tp>)
|
||||
{
|
||||
// if __end > __start, we know that the range is always positive. Similarly, __v is positive if unsigned.
|
||||
// this optimization is useful when __start and __end are compile-time constants, or when in_range is used multiple
|
||||
// times with the same range
|
||||
using _Up = ::cuda::std::conditional_t<(sizeof(_Tp) <= sizeof(unsigned)), unsigned, _Tp>; // at least 32-bit
|
||||
const auto __start1 = static_cast<_Up>(__start);
|
||||
const auto __end1 = static_cast<_Up>(__end);
|
||||
const auto __v1 = static_cast<_Up>(__v);
|
||||
const auto __range = __end1 - __start1;
|
||||
return (__v1 - __start1) <= __range;
|
||||
}
|
||||
else
|
||||
{
|
||||
return __v >= __start && __v <= __end;
|
||||
}
|
||||
}
|
||||
|
||||
_CCCL_END_NAMESPACE_CUDA
|
||||
|
||||
#include <cuda/std/__cccl/epilogue.h>
|
||||
|
||||
#endif // _CUDA___UTILITY_IN_RANGE_H
|
||||
36
cccl_upstream/libcudacxx/include/cuda/__utility/inherit.h
Normal file
36
cccl_upstream/libcudacxx/include/cuda/__utility/inherit.h
Normal file
@@ -0,0 +1,36 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of libcu++, the C++ Standard Library for your entire system,
|
||||
// under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
// SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef _CUDA___UTILITY_INHERIT_H
|
||||
#define _CUDA___UTILITY_INHERIT_H
|
||||
|
||||
#include <cuda/std/detail/__config>
|
||||
|
||||
#if defined(_CCCL_IMPLICIT_SYSTEM_HEADER_GCC)
|
||||
# pragma GCC system_header
|
||||
#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_CLANG)
|
||||
# pragma clang system_header
|
||||
#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_MSVC)
|
||||
# pragma system_header
|
||||
#endif // no system header
|
||||
|
||||
#include <cuda/std/__cccl/prologue.h>
|
||||
|
||||
_CCCL_BEGIN_NAMESPACE_CUDA
|
||||
|
||||
template <class... _Types>
|
||||
struct _CCCL_TYPE_VISIBILITY_DEFAULT _CCCL_DECLSPEC_EMPTY_BASES __inherit : _Types...
|
||||
{};
|
||||
|
||||
_CCCL_END_NAMESPACE_CUDA
|
||||
|
||||
#include <cuda/std/__cccl/epilogue.h>
|
||||
|
||||
#endif // _CUDA___UTILITY_INHERIT_H
|
||||
29
cccl_upstream/libcudacxx/include/cuda/__utility/no_init.h
Normal file
29
cccl_upstream/libcudacxx/include/cuda/__utility/no_init.h
Normal file
@@ -0,0 +1,29 @@
|
||||
#ifndef _CUDA___UTILITY_NO_INIT_H
|
||||
#define _CUDA___UTILITY_NO_INIT_H
|
||||
|
||||
#include <cuda/std/detail/__config>
|
||||
|
||||
#if defined(_CCCL_IMPLICIT_SYSTEM_HEADER_GCC)
|
||||
# pragma GCC system_header
|
||||
#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_CLANG)
|
||||
# pragma clang system_header
|
||||
#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_MSVC)
|
||||
# pragma system_header
|
||||
#endif // no system header
|
||||
|
||||
#include <cuda/std/__cccl/prologue.h>
|
||||
|
||||
_CCCL_BEGIN_NAMESPACE_CUDA
|
||||
|
||||
struct _CCCL_TYPE_VISIBILITY_DEFAULT no_init_t
|
||||
{
|
||||
_CCCL_HIDE_FROM_ABI explicit no_init_t() = default;
|
||||
};
|
||||
|
||||
_CCCL_GLOBAL_CONSTANT no_init_t no_init{};
|
||||
|
||||
_CCCL_END_NAMESPACE_CUDA
|
||||
|
||||
#include <cuda/std/__cccl/epilogue.h>
|
||||
|
||||
#endif // _CUDA___UTILITY_NO_INIT_H
|
||||
79
cccl_upstream/libcudacxx/include/cuda/__utility/static_for.h
Normal file
79
cccl_upstream/libcudacxx/include/cuda/__utility/static_for.h
Normal file
@@ -0,0 +1,79 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
// SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef _CUDA___UTILITY_STATIC_FOR_H
|
||||
#define _CUDA___UTILITY_STATIC_FOR_H
|
||||
|
||||
#include <cuda/std/detail/__config>
|
||||
|
||||
#if defined(_CCCL_IMPLICIT_SYSTEM_HEADER_GCC)
|
||||
# pragma GCC system_header
|
||||
#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_CLANG)
|
||||
# pragma clang system_header
|
||||
#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_MSVC)
|
||||
# pragma system_header
|
||||
#endif // no system header
|
||||
|
||||
#include <cuda/std/__type_traits/integral_constant.h>
|
||||
#include <cuda/std/__utility/forward.h>
|
||||
#include <cuda/std/__utility/integer_sequence.h>
|
||||
|
||||
#include <cuda/std/__cccl/prologue.h>
|
||||
|
||||
_CCCL_BEGIN_NAMESPACE_CUDA
|
||||
|
||||
template <typename _SizeType, _SizeType _Start, _SizeType _Step, typename _Operator, _SizeType... _Indices, typename... _TArgs>
|
||||
_CCCL_API constexpr void
|
||||
__static_for_impl(_Operator __op, ::cuda::std::integer_sequence<_SizeType, _Indices...>, _TArgs&&... __args) noexcept(
|
||||
(true && ... && noexcept(__op(::cuda::std::integral_constant<_SizeType, (_Indices * _Step + _Start)>{}, __args...))))
|
||||
{
|
||||
(__op(::cuda::std::integral_constant<_SizeType, (_Indices * _Step + _Start)>{}, __args...), ...);
|
||||
}
|
||||
|
||||
template <typename _Tp, _Tp _Size, typename _Operator, typename... _TArgs>
|
||||
_CCCL_API constexpr void
|
||||
static_for(_Operator __op, _TArgs&&... __args) noexcept(noexcept(::cuda::__static_for_impl<_Tp, 0, 1>(
|
||||
__op, ::cuda::std::make_integer_sequence<_Tp, _Size>{}, ::cuda::std::forward<_TArgs>(__args)...)))
|
||||
{
|
||||
::cuda::__static_for_impl<_Tp, 0, 1>(
|
||||
__op, ::cuda::std::make_integer_sequence<_Tp, _Size>{}, ::cuda::std::forward<_TArgs>(__args)...);
|
||||
}
|
||||
|
||||
template <typename _Tp, _Tp _Start, _Tp _End, _Tp _Step = 1, typename _Operator, typename... _TArgs>
|
||||
_CCCL_API constexpr void
|
||||
static_for(_Operator __op, _TArgs&&... __args) noexcept(noexcept(::cuda::__static_for_impl<_Tp, _Start, _Step>(
|
||||
__op, ::cuda::std::make_integer_sequence<_Tp, (_End - _Start) / _Step>{}, ::cuda::std::forward<_TArgs>(__args)...)))
|
||||
{
|
||||
::cuda::__static_for_impl<_Tp, _Start, _Step>(
|
||||
__op, ::cuda::std::make_integer_sequence<_Tp, (_End - _Start) / _Step>{}, ::cuda::std::forward<_TArgs>(__args)...);
|
||||
}
|
||||
|
||||
template <auto _Size, typename _Operator, typename... _TArgs>
|
||||
_CCCL_API constexpr void static_for(_Operator __op, _TArgs&&... __args) noexcept(
|
||||
noexcept(::cuda::static_for<decltype(_Size), _Size>(__op, ::cuda::std::forward<_TArgs>(__args)...)))
|
||||
{
|
||||
::cuda::static_for<decltype(_Size), _Size>(__op, ::cuda::std::forward<_TArgs>(__args)...);
|
||||
}
|
||||
|
||||
template <auto _Start,
|
||||
decltype(_Start) _End,
|
||||
decltype(_Start) _Step = decltype(_Start){1},
|
||||
typename _Operator,
|
||||
typename... _TArgs>
|
||||
_CCCL_API constexpr void static_for(_Operator __op, _TArgs&&... __args) noexcept(
|
||||
noexcept(::cuda::static_for<decltype(_Start), _Start, _End, _Step>(__op, ::cuda::std::forward<_TArgs>(__args)...)))
|
||||
{
|
||||
::cuda::static_for<decltype(_Start), _Start, _End, _Step>(__op, ::cuda::std::forward<_TArgs>(__args)...);
|
||||
}
|
||||
|
||||
_CCCL_END_NAMESPACE_CUDA
|
||||
|
||||
#include <cuda/std/__cccl/epilogue.h>
|
||||
|
||||
#endif // _CUDA___UTILITY_STATIC_FOR_H
|
||||
Reference in New Issue
Block a user