From feba45d9cc29eb5af14f709b4cdd973fbea4542c Mon Sep 17 00:00:00 2001 From: Eric Niebler Date: Thu, 5 Feb 2026 14:48:19 -0800 Subject: [PATCH 1/5] add helpers for creating type-erasing wrappers --- .gitignore | 1 + include/stdexec/__detail/__any.hpp | 1778 ++++++++++++++++++++++ include/stdexec/__detail/__config.hpp | 33 +- include/stdexec/__detail/__debug.hpp | 11 - include/stdexec/__detail/__utility.hpp | 153 +- include/stdexec/__detail/__write_env.hpp | 1 - test/CMakeLists.txt | 1 + test/stdexec/detail/test_any.cpp | 235 +++ 8 files changed, 2186 insertions(+), 27 deletions(-) create mode 100644 include/stdexec/__detail/__any.hpp create mode 100644 test/stdexec/detail/test_any.cpp diff --git a/.gitignore b/.gitignore index d5f0680d0..0e66cac78 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,4 @@ callgrind.* a.out *.code-workspace /include/asioexec/asio_config.hpp +.venv-codex diff --git a/include/stdexec/__detail/__any.hpp b/include/stdexec/__detail/__any.hpp new file mode 100644 index 000000000..a2b558551 --- /dev/null +++ b/include/stdexec/__detail/__any.hpp @@ -0,0 +1,1778 @@ +/* + * Copyright (c) 2026 NVIDIA Corporation + * + * Licensed under the Apache License Version 2.0 with LLVM Exceptions + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * https://llvm.org/LICENSE.txt + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#pragma once + +#include "__concepts.hpp" +#include "__config.hpp" +#include "__type_traits.hpp" +#include "__typeinfo.hpp" +#include "__utility.hpp" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace STDEXEC::__any { + + ////////////////////////////////////////////////////////////////////////////////////////// + //! any: a library for ad hoc polymorphism with value semantics + //! + //! @par Terminology: + //! + //! - "root": + //! + //! A type satisfying the @c root concept that is used as the nucleus of a "model". + //! There are 5 root types: + //! + //! - @c __iroot: the abstract root + //! - @c __value_root: holds a concrete value + //! - @c __reference_root: holds a concrete reference + //! - @c __value_proxy_root: holds a type-erased value model + //! - @c __reference_proxy_root: holds a type-erased reference model + //! + //! Aside from @c __iroot, all root types inherit from @c __iabstract, where + //! @c Interface is the interface that the root type implements. + //! + //! The @c root concept is defined as: + //! + //! @code + //! template + //! concept root = requires (Root& root) + //! { + //! __any::__value(root); + //! { __any::reset(root); } -> std::same_as; + //! { __any::type(root) } -> std::same_as; + //! { __any::data(root) } -> std::same_as; + //! { __any::empty(root) } -> std::same_as; + //! }; + //! @endcode + //! + //! - "model": + //! + //! A polymorphic wrapper around a root that is constructed by recursively applying a + //! given interface and its base interfaces to the root type. For example, given an + //! interface @c Derived that __extends @c Base, the value proxy model is a type derived + //! from @c Derived>>. Model types implement their given + //! interfaces in terms of the root type. There are 5 model types: + //! + //! - @c __iabstract: akin to an abstract base class for the + //! interface + //! - @c __value_model: implements the interface for a concrete value + //! - @c __reference_model: implements the interface for a concrete + //! reference + //! - @c __value_proxy_model: implements the interface over a type-erased + //! value model + //! - @c __reference_proxy_model: implements the interface over a type-erased + //! reference model + //! + //! - "proxy": + //! + //! A level of indirection that stores either a type-erased model in a small buffer or a + //! pointer to an object stored elsewhere. The @c __value_proxy_root and @c + //! __reference_proxy_root types model the @c root concept and contain an array of bytes + //! in which they stores either a polymorphic model in-situ or a (tagged) pointer to a + //! heap-allocated model. The @c __value_proxy_model and @c __reference_proxy_model types + //! implement the given interface in terms of the root type. + //! + //! @par Notes: + //! + //! - @c Interface inherits directly from @c any::interface, which + //! inherits directly from @c Base. + //! + //! - Given an interface template @c Derived that __extends @c Base, the type + //! @c __iabstract is derived from @c __iabstract. + //! + //! - In the case of multiple interface extension, the inheritance is forced to be linear. + //! As a result, for an interface @c C that __extends @c A and @c B (in that order), + //! @c __iabstract will have a linear inheritance hierarchy; it will be an alias for + //! @c C>>. The result is that @c __iabstract inherits from @c __iabstract + //! but not from @c __iabstract. + //! + //! - The "`__proxy_root`" types both implement an @c emplace function that accepts a + //! concrete value or reference, wraps it in the appropriate "`__model`" type, and stores + //! it either in-situ or on the heap depending on its size and whether it is nothrow + //! moveable. + //! + //! - The @c __root types (excluding @c __iroot) all inherit from @c __iabstract. + //! The @c __model types implement the interface in terms of the root type. + //! + //! - @c any inherits from @c __value_proxy_model, which in turn inherits + //! from @c Derived>>, which in turn inherits from + //! @c Derived> (aka @c __iabstract ). + //! + //! - @c __any_ptr is implemented in terms of a mutable private + //! @c __reference_proxy_model data member, which in turn inherits from + //! @c Derived>>. + //! + //! - For every @c any instantiation, there are 5 instantiations of + //! @c Interface: + //! + //! 1. @c Interface<...Bases...<__iroot>>>...> + //! 2. @c Interface<...Bases...<__value_root>...> + //! 3. @c Interface<...Bases...<__reference_root>...> + //! 4. @c Interface<...Bases...<__value_proxy_root>...> + //! 5. @c Interface<...Bases...<__reference_proxy_root>...> + + constexpr size_t __default_buffer_size = 3 * sizeof(void *); + constexpr char const *__pure_virt_msg = "internal error: pure virtual %s() called\n"; + + ////////////////////////////////////////////////////////////////////////////////////////// + // forward declarations + + // any types + template