[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:
EngineX CI
2026-07-30 09:35:51 +00:00
parent b4d01f481e
commit 56fd68e7dd
8871 changed files with 1454674 additions and 0 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View 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

View 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

View 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

View 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

View 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

View 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