From 56fd46be77bc2164b603bd9e300655a1e391759a Mon Sep 17 00:00:00 2001
From: Hartmut Kaiser <hartmut.kaiser@gmail.com>
Date: Sat, 5 Oct 2024 15:09:15 -0500
Subject: [PATCH] Enable variable partition sizes for partitioned_vector

---
 .github/CONTRIBUTING.md                       |  10 +-
 cmake/HPX_SetupNanobench.cmake                |   6 +
 .../partitioned_vector/CMakeLists.txt         |   2 +-
 .../partitioned_vector_component_decl.hpp     |  72 ++++-
 .../partitioned_vector_component_impl.hpp     | 105 +++++--
 .../partitioned_vector_decl.hpp               | 297 +++++++++++++-----
 .../partitioned_vector_impl.hpp               | 153 +++++----
 .../partitioned_vector_predef.hpp             |  29 +-
 .../partitioned_vector_segmented_iterator.hpp | 284 ++++++++++-------
 .../serialization/partitioned_vector.hpp      | 119 +++++++
 .../hpx/include/partitioned_vector.hpp        |   4 +-
 .../hpx/include/partitioned_vector_predef.hpp |   6 +-
 .../serialization/partitioned_vector.hpp      |  39 ---
 .../partitioned_vector_component_double.cpp   |   7 +
 .../src/partitioned_vector_component_int.cpp  |  13 +
 ...artitioned_vector_component_std_string.cpp |   7 +
 .../unit/serialization_partitioned_vector.cpp |  25 +-
 .../containers/unordered/unordered_map.hpp    |   4 +-
 .../hpx/datastructures/member_pack.hpp        |   2 +-
 libs/core/functional/CMakeLists.txt           |   1 +
 .../hpx/functional/reference_wrapper.hpp      |  60 ++++
 .../hpx/iterator_support/iterator_facade.hpp  |  34 +-
 libs/core/testing/src/performance.cpp         |   4 +-
 .../hpx/actions_base/component_action.hpp     |   3 +-
 .../traits/is_distribution_policy.hpp         |  32 ++
 .../transfer_continuation_action.hpp          |  12 +-
 .../host/target_distribution_policy.hpp       |   7 +-
 .../full/distribution_policies/CMakeLists.txt |   1 +
 .../binpacking_distribution_policy.hpp        |  14 +-
 .../colocating_distribution_policy.hpp        |  67 +++-
 .../container_distribution_policy.hpp         |  90 ++++--
 .../default_distribution_policy.hpp           |  46 +--
 ...explicit_container_distribution_policy.hpp | 160 ++++++++++
 .../target_distribution_policy.hpp            |   4 +-
 libs/full/naming/src/credit_handling.cpp      |  10 +-
 .../create_component_helpers.hpp              |  23 +-
 .../include/hpx/runtime_components/new.hpp    |   4 +-
 .../runtime_distributed/runtime_support.hpp   |  36 +--
 .../server/runtime_support.hpp                |  57 ++--
 .../stubs/runtime_support.hpp                 |  18 +-
 .../segmented_algorithms/all_any_none.hpp     |   9 +-
 .../segmented_algorithms/for_each.hpp         |  64 ++--
 .../unit/partitioned_vector_for_each.cpp      |  88 ++++--
 .../partitioned_vector_inclusive_scan.cpp     |   9 +-
 44 files changed, 1454 insertions(+), 583 deletions(-)
 create mode 100644 components/containers/partitioned_vector/include/hpx/components/containers/partitioned_vector/serialization/partitioned_vector.hpp
 delete mode 100644 components/containers/partitioned_vector/include/hpx/runtime/serialization/partitioned_vector.hpp
 create mode 100644 libs/core/functional/include/hpx/functional/reference_wrapper.hpp
 create mode 100644 libs/full/distribution_policies/include/hpx/distribution_policies/explicit_container_distribution_policy.hpp

diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md
index 6278ac283b68..244715d3c14a 100644
--- a/.github/CONTRIBUTING.md
+++ b/.github/CONTRIBUTING.md
@@ -1,4 +1,4 @@
-<!-- Copyright (c) 2014-2022 Hartmut Kaiser                                       -->
+<!-- Copyright (c) 2014-2024 Hartmut Kaiser                                       -->
 <!--                                                                              -->
 <!-- SPDX-License-Identifier: BSL-1.0                                             -->
 <!-- Distributed under the Boost Software License, Version 1.0. (See accompanying -->
@@ -19,10 +19,10 @@ i.e. pull requests.
 
 The easiest ways to get in contact with us are listed here:
 
-* Mailing list: [hpx-users@stellar-group.org](email:hpx-users@stellar-group.org), [hpx-devel@stellar-group.org](email:hpx-devel@stellar-group.org)
-* IRC channel:  #ste||ar on Libra.Chat
-* Blog:         [hpx.stellar-group.org](hpx.stellar-group.org)
-* More options: See our [support page](https://github.com/STEllAR-GROUP/hpx/blob/master/.github/SUPPORT.md)
+* Mailing list:    [hpx-users@stellar-group.org](email:hpx-users@stellar-group.org), [hpx-devel@stellar-group.org](email:hpx-devel@stellar-group.org)
+* Discord server:  [#ste||ar](https://discord.gg/Tn9QuzVjvy)
+* Blog:            [hpx.stellar-group.org](hpx.stellar-group.org)
+* More options:    See our [support page](https://github.com/STEllAR-GROUP/hpx/blob/master/.github/SUPPORT.md)
 
 The basic approach is to find something fun you want to fix, hack it up, and
 send a `git diff` as a mail attachment to [hpx-devel@stellar-group.org](email:hpx-devel@stellar-group.org)
diff --git a/cmake/HPX_SetupNanobench.cmake b/cmake/HPX_SetupNanobench.cmake
index 14ba9880a209..431e0ea9bf18 100644
--- a/cmake/HPX_SetupNanobench.cmake
+++ b/cmake/HPX_SetupNanobench.cmake
@@ -1,3 +1,9 @@
+# Copyright (c) 2024 Hartmut Kaiser
+#
+# SPDX-License-Identifier: BSL-1.0
+# Distributed under the Boost Software License, Version 1.0. (See accompanying
+# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
 include(FetchContent)
 
 fetchcontent_declare(
diff --git a/components/containers/partitioned_vector/CMakeLists.txt b/components/containers/partitioned_vector/CMakeLists.txt
index c0aa1f2433fc..2a4e8a5da088 100644
--- a/components/containers/partitioned_vector/CMakeLists.txt
+++ b/components/containers/partitioned_vector/CMakeLists.txt
@@ -30,10 +30,10 @@ set(partitioned_vector_headers
     hpx/components/containers/partitioned_vector/partitioned_vector_segmented_iterator.hpp
     hpx/components/containers/partitioned_vector/partitioned_vector_view.hpp
     hpx/components/containers/partitioned_vector/partitioned_vector_view_iterator.hpp
+    hpx/components/containers/partitioned_vector/serialization/partitioned_vector.hpp
     hpx/include/partitioned_vector.hpp
     hpx/include/partitioned_vector_predef.hpp
     hpx/include/partitioned_vector_view.hpp
-    hpx/runtime/serialization/partitioned_vector.hpp
 )
 
 set(partitioned_vector_sources
diff --git a/components/containers/partitioned_vector/include/hpx/components/containers/partitioned_vector/partitioned_vector_component_decl.hpp b/components/containers/partitioned_vector/include/hpx/components/containers/partitioned_vector/partitioned_vector_component_decl.hpp
index 9d3f7ea7daf5..785ef1076d20 100644
--- a/components/containers/partitioned_vector/include/hpx/components/containers/partitioned_vector/partitioned_vector_component_decl.hpp
+++ b/components/containers/partitioned_vector/include/hpx/components/containers/partitioned_vector/partitioned_vector_component_decl.hpp
@@ -24,6 +24,7 @@
 #include <hpx/components/client_base.hpp>
 #include <hpx/components_base/server/component_base.hpp>
 #include <hpx/components_base/server/locking_hook.hpp>
+#include <hpx/functional/invoke_result.hpp>
 #include <hpx/preprocessor/cat.hpp>
 #include <hpx/preprocessor/expand.hpp>
 #include <hpx/preprocessor/nargs.hpp>
@@ -39,11 +40,33 @@
 
 #include <hpx/config/warnings_prefix.hpp>
 
+namespace hpx::detail {
+
+    HPX_HAS_XXX_TRAIT_DEF(allocator_type);
+
+    template <typename T, typename Data, typename Enable = void>
+    struct extract_allocator_type
+    {
+        using type = std::allocator<T>;
+    };
+
+    template <typename T, typename Data>
+    struct extract_allocator_type<T, Data,
+        std::enable_if_t<has_allocator_type_v<Data>>>
+    {
+        using type = typename Data::allocator_type;
+    };
+
+    template <typename T, typename Data>
+    using extract_allocator_type_t =
+        typename extract_allocator_type<T, Data>::type;
+}    // namespace hpx::detail
+
 namespace hpx::server {
 
     /// \brief This is the basic wrapper class for stl vector.
     ///
-    /// This contains the implementation of the partitioned_vector_partition's
+    /// This contains the implementation of the partitioned_vector partition's
     /// component functionality.
     template <typename T, typename Data>
     class partitioned_vector
@@ -53,7 +76,7 @@ namespace hpx::server {
     public:
         using data_type = Data;
 
-        using allocator_type = typename data_type::allocator_type;
+        using allocator_type = hpx::detail::extract_allocator_type_t<T, Data>;
         using size_type = typename data_type::size_type;
         using iterator_type = typename data_type::iterator;
         using const_iterator_type = typename data_type::const_iterator;
@@ -71,7 +94,9 @@ namespace hpx::server {
         /// size 0.
         partitioned_vector();
 
-        explicit partitioned_vector(size_type partition_size);
+        explicit partitioned_vector(std::size_t partnum,
+            std::vector<size_type> const& partition_sizes,
+            traits::create_mode = traits::create_mode::resize);
 
         /// Constructor which create and initialize partitioned_vector_partition
         /// with all elements as \a val.
@@ -79,9 +104,11 @@ namespace hpx::server {
         /// param partition_size The size of vector
         /// param val Default value for the elements in partitioned_vector_partition
         ///
-        partitioned_vector(size_type partition_size, T const& val);
+        partitioned_vector(std::size_t partnum,
+            std::vector<size_type> const& partition_sizes, T const& val);
 
-        partitioned_vector(size_type partition_size, T const& val,
+        partitioned_vector(std::size_t partnum,
+            std::vector<size_type> const& partition_sizes, T const& val,
             allocator_type const& alloc);
 
         // support components::copy
@@ -274,13 +301,31 @@ namespace hpx::server {
         // HPX_DEFINE_COMPONENT_ACTION(partitioned_vector_partition, clear)
         HPX_DEFINE_COMPONENT_DIRECT_ACTION(partitioned_vector, get_copied_data)
         HPX_DEFINE_COMPONENT_DIRECT_ACTION(partitioned_vector, set_data)
+
+        /// Invoke given function on given element
+        ///
+        /// \return This returns whatever the given function invocation returns
+        template <typename F, typename... Ts>
+        util::invoke_result_t<F, T, Ts...> apply(
+            std::size_t pos, F f, Ts... ts);
+
+        template <typename F, typename... Ts>
+        struct apply_action
+          : hpx::actions::make_action_t<
+                decltype(&partitioned_vector::apply<F, Ts...>),
+                &partitioned_vector::apply<F, Ts...>, apply_action<F, Ts...>>
+        {
+        };
     };
 }    // namespace hpx::server
 
 ///////////////////////////////////////////////////////////////////////////////
+#if 0
+#define HPX_REGISTER_PARTITIONED_VECTOR_DECLARATION(...)
+#else
 #define HPX_REGISTER_PARTITIONED_VECTOR_DECLARATION(...)                       \
     HPX_REGISTER_VECTOR_DECLARATION_(__VA_ARGS__)                              \
-/**/
+    /**/
 #define HPX_REGISTER_VECTOR_DECLARATION_(...)                                  \
     HPX_PP_EXPAND(HPX_PP_CAT(HPX_REGISTER_VECTOR_DECLARATION_,                 \
         HPX_PP_NARGS(__VA_ARGS__))(__VA_ARGS__))                               \
@@ -307,16 +352,17 @@ namespace hpx::server {
 
 #define HPX_REGISTER_VECTOR_DECLARATION_1(type)                                \
     HPX_REGISTER_VECTOR_DECLARATION_2(type, std::vector<type>)                 \
-/**/
+    /**/
 #define HPX_REGISTER_VECTOR_DECLARATION_2(type, data)                          \
     HPX_REGISTER_VECTOR_DECLARATION_3(type, data, type)                        \
-/**/
+    /**/
 #define HPX_REGISTER_VECTOR_DECLARATION_3(type, data, name)                    \
     typedef ::hpx::server::partitioned_vector<type, data> HPX_PP_CAT(          \
         __partitioned_vector_, HPX_PP_CAT(type, name));                        \
     HPX_REGISTER_VECTOR_DECLARATION_IMPL(                                      \
         HPX_PP_CAT(__partitioned_vector_, HPX_PP_CAT(type, name)), name)       \
     /**/
+#endif
 
 namespace hpx {
 
@@ -559,8 +605,7 @@ namespace hpx {
         ///
         hpx::future<typename server_type::data_type> get_copied_data() const;
 
-        /// Updates the data owned by the partition_vector
-        /// component.
+        /// Updates the data owned by the partition_vector component.
         ///
         /// \return This returns the data of the partition_vector
         ///
@@ -574,6 +619,13 @@ namespace hpx {
         ///
         hpx::future<void> set_data(
             typename server_type::data_type&& other) const;
+
+        /// Invoke given function on given element
+        ///
+        /// \return This returns whatever the given function invocation returns
+        template <typename F, typename... Ts>
+        hpx::future<util::invoke_result_t<F, T, Ts...>> apply(
+            std::size_t pos, F&& f, Ts&&... ts);
     };
 }    // namespace hpx
 
diff --git a/components/containers/partitioned_vector/include/hpx/components/containers/partitioned_vector/partitioned_vector_component_impl.hpp b/components/containers/partitioned_vector/include/hpx/components/containers/partitioned_vector/partitioned_vector_component_impl.hpp
index dd011ba4738f..4ff99e4f6ce2 100644
--- a/components/containers/partitioned_vector/include/hpx/components/containers/partitioned_vector/partitioned_vector_component_impl.hpp
+++ b/components/containers/partitioned_vector/include/hpx/components/containers/partitioned_vector/partitioned_vector_component_impl.hpp
@@ -37,24 +37,33 @@ namespace hpx::server {
 
     template <typename T, typename Data>
     HPX_PARTITIONED_VECTOR_SPECIALIZATION_EXPORT
-    partitioned_vector<T, Data>::partitioned_vector(size_type partition_size)
-      : partitioned_vector_partition_(partition_size)
+    partitioned_vector<T, Data>::partitioned_vector(std::size_t partnum,
+        std::vector<size_type> const& partition_sizes, traits::create_mode mode)
     {
+        if (mode == traits::create_mode::resize)
+        {
+            partitioned_vector_partition_.resize(partition_sizes[partnum]);
+        }
+        else
+        {
+            partitioned_vector_partition_.reserve(partition_sizes[partnum]);
+        }
     }
 
     template <typename T, typename Data>
     HPX_PARTITIONED_VECTOR_SPECIALIZATION_EXPORT
-    partitioned_vector<T, Data>::partitioned_vector(
-        size_type partition_size, T const& val)
-      : partitioned_vector_partition_(partition_size, val)
+    partitioned_vector<T, Data>::partitioned_vector(std::size_t partnum,
+        std::vector<size_type> const& partition_sizes, T const& val)
+      : partitioned_vector_partition_(partition_sizes[partnum], val)
     {
     }
 
     template <typename T, typename Data>
     HPX_PARTITIONED_VECTOR_SPECIALIZATION_EXPORT
-    partitioned_vector<T, Data>::partitioned_vector(
-        size_type partition_size, T const& val, allocator_type const& alloc)
-      : partitioned_vector_partition_(partition_size, val, alloc)
+    partitioned_vector<T, Data>::partitioned_vector(std::size_t partnum,
+        std::vector<size_type> const& partition_sizes, T const& val,
+        allocator_type const& alloc)
+      : partitioned_vector_partition_(partition_sizes[partnum], val, alloc)
     {
     }
 
@@ -266,12 +275,20 @@ namespace hpx::server {
     {
         partitioned_vector_partition_.clear();
     }
+
+    template <typename T, typename Data>
+    template <typename F, typename... Ts>
+    HPX_PARTITIONED_VECTOR_SPECIALIZATION_EXPORT
+        util::invoke_result_t<F, T, Ts...>
+        partitioned_vector<T, Data>::apply(std::size_t pos, F f, Ts... ts)
+    {
+        return HPX_INVOKE(
+            HPX_MOVE(f), partitioned_vector_partition_[pos], HPX_MOVE(ts)...);
+    }
 }    // namespace hpx::server
 
 ///////////////////////////////////////////////////////////////////////////////
-#define HPX_REGISTER_PARTITIONED_VECTOR(...)                                   \
-    HPX_REGISTER_VECTOR_(__VA_ARGS__)                                          \
-/**/
+#define HPX_REGISTER_PARTITIONED_VECTOR(...) HPX_REGISTER_VECTOR_(__VA_ARGS__)
 #define HPX_REGISTER_VECTOR_(...)                                              \
     HPX_PP_EXPAND(HPX_PP_CAT(HPX_REGISTER_VECTOR_, HPX_PP_NARGS(__VA_ARGS__))( \
         __VA_ARGS__))                                                          \
@@ -294,6 +311,9 @@ namespace hpx::server {
         HPX_PP_CAT(__vector_get_copied_data_action_, name))                    \
     HPX_REGISTER_ACTION(                                                       \
         type::set_data_action, HPX_PP_CAT(__vector_set_data_action_, name))    \
+    /**/
+
+#define HPX_REGISTER_VECTOR_COMPONENT_IMPL(type, name)                         \
     typedef ::hpx::components::component<type> HPX_PP_CAT(__vector_, name);    \
     HPX_REGISTER_COMPONENT(HPX_PP_CAT(__vector_, name))                        \
     /**/
@@ -301,16 +321,28 @@ namespace hpx::server {
 #define HPX_REGISTER_VECTOR_1(type)                                            \
     HPX_REGISTER_VECTOR_3(                                                     \
         type, std::vector<type>, HPX_PP_CAT(std_vector_, type))                \
-/**/
+    /**/
 #define HPX_REGISTER_VECTOR_2(type, data)                                      \
     HPX_REGISTER_VECTOR_3(type, data, HPX_PP_CAT(type, data))                  \
-/**/
+    /**/
+
+#if 0
+#define HPX_REGISTER_VECTOR_3(type, data, name)                                \
+    typedef ::hpx::server::partitioned_vector<type, data> HPX_PP_CAT(          \
+        __partitioned_vector_, HPX_PP_CAT(type, name));                        \
+    HPX_REGISTER_VECTOR_COMPONENT_IMPL(                                        \
+        HPX_PP_CAT(__partitioned_vector_, HPX_PP_CAT(type, name)), name)       \
+    /**/
+#else
 #define HPX_REGISTER_VECTOR_3(type, data, name)                                \
     typedef ::hpx::server::partitioned_vector<type, data> HPX_PP_CAT(          \
         __partitioned_vector_, HPX_PP_CAT(type, name));                        \
     HPX_REGISTER_VECTOR_IMPL(                                                  \
         HPX_PP_CAT(__partitioned_vector_, HPX_PP_CAT(type, name)), name)       \
+    HPX_REGISTER_VECTOR_COMPONENT_IMPL(                                        \
+        HPX_PP_CAT(__partitioned_vector_, HPX_PP_CAT(type, name)), name)       \
     /**/
+#endif
 
 namespace hpx {
 
@@ -346,7 +378,7 @@ namespace hpx {
     {
 #if !defined(HPX_COMPUTE_DEVICE_CODE)
         HPX_ASSERT(this->get_id());
-        return hpx::async<typename server_type::size_action>(this->get_id());
+        return hpx::async(typename server_type::size_action(), this->get_id());
 #else
         HPX_ASSERT(false);
         return hpx::make_ready_future(std::size_t{});
@@ -375,8 +407,8 @@ namespace hpx {
     {
 #if !defined(HPX_COMPUTE_DEVICE_CODE)
         HPX_ASSERT(this->get_id());
-        return hpx::async<typename server_type::resize_action>(
-            this->get_id(), n, val);
+        return hpx::async(
+            typename server_type::resize_action(), this->get_id(), n, val);
 #else
         HPX_ASSERT(false);
         return hpx::make_ready_future();
@@ -398,8 +430,8 @@ namespace hpx {
     {
 #if !defined(HPX_COMPUTE_DEVICE_CODE)
         HPX_ASSERT(this->get_id());
-        return hpx::async<typename server_type::get_value_action>(
-            this->get_id(), pos);
+        return hpx::async(
+            typename server_type::get_value_action(), this->get_id(), pos);
 #else
         HPX_ASSERT(false);
         return hpx::future<T>{};
@@ -421,8 +453,8 @@ namespace hpx {
     {
 #if !defined(HPX_COMPUTE_DEVICE_CODE)
         HPX_ASSERT(this->get_id());
-        return hpx::async<typename server_type::get_values_action>(
-            this->get_id(), pos);
+        return hpx::async(
+            typename server_type::get_values_action(), this->get_id(), pos);
 #else
         HPX_ASSERT(false);
         return hpx::make_ready_future(std::vector<T>{});
@@ -452,7 +484,7 @@ namespace hpx {
     {
 #if !defined(HPX_COMPUTE_DEVICE_CODE)
         HPX_ASSERT(this->get_id());
-        return hpx::async<typename server_type::set_value_action>(
+        return hpx::async(typename server_type::set_value_action(),
             this->get_id(), pos, HPX_MOVE(val));
 #else
         HPX_ASSERT(false);
@@ -467,8 +499,8 @@ namespace hpx {
     {
 #if !defined(HPX_COMPUTE_DEVICE_CODE)
         HPX_ASSERT(this->get_id());
-        return hpx::async<typename server_type::set_value_action>(
-            this->get_id(), pos, val);
+        return hpx::async(
+            typename server_type::set_value_action(), this->get_id(), pos, val);
 #else
         HPX_ASSERT(false);
         return hpx::make_ready_future();
@@ -491,7 +523,7 @@ namespace hpx {
     {
 #if !defined(HPX_COMPUTE_DEVICE_CODE)
         HPX_ASSERT(this->get_id());
-        return hpx::async<typename server_type::set_values_action>(
+        return hpx::async(typename server_type::set_values_action(),
             this->get_id(), pos, val);
 #else
         HPX_ASSERT(false);
@@ -515,8 +547,8 @@ namespace hpx {
     {
 #if !defined(HPX_COMPUTE_DEVICE_CODE)
         HPX_ASSERT(this->get_id());
-        return hpx::async<typename server_type::get_copied_data_action>(
-            this->get_id());
+        return hpx::async(
+            typename server_type::get_copied_data_action(), this->get_id());
 #else
         HPX_ASSERT(false);
         return hpx::make_ready_future(typename partitioned_vector_partition<T,
@@ -539,11 +571,30 @@ namespace hpx {
     {
 #if !defined(HPX_COMPUTE_DEVICE_CODE)
         HPX_ASSERT(this->get_id());
-        return hpx::async<typename server_type::set_data_action>(
+        return hpx::async(typename server_type::set_data_action(),
             this->get_id(), HPX_MOVE(other));
 #else
         HPX_ASSERT(false);
         return hpx::make_ready_future();
+#endif
+    }
+
+    template <typename T, typename Data /*= std::vector<T> */>
+    template <typename F, typename... Ts>
+    HPX_PARTITIONED_VECTOR_SPECIALIZATION_EXPORT
+        hpx::future<util::invoke_result_t<F, T, Ts...>>
+        partitioned_vector_partition<T, Data>::apply(
+            [[maybe_unused]] std::size_t pos, [[maybe_unused]] F&& f,
+            [[maybe_unused]] Ts&&... ts)
+    {
+#if !defined(HPX_COMPUTE_DEVICE_CODE)
+        HPX_ASSERT(this->get_id());
+        return hpx::async(
+            typename server_type::template apply_action<F, Ts...>(),
+            this->get_id(), pos, HPX_FORWARD(F, f), HPX_FORWARD(Ts, ts)...);
+#else
+        HPX_ASSERT(false);
+        return hpx::make_ready_future(util::invoke_result_t<F&&, Ts&&...>());
 #endif
     }
 }    // namespace hpx
diff --git a/components/containers/partitioned_vector/include/hpx/components/containers/partitioned_vector/partitioned_vector_decl.hpp b/components/containers/partitioned_vector/include/hpx/components/containers/partitioned_vector/partitioned_vector_decl.hpp
index c4e582c086c4..c645ac2801b3 100644
--- a/components/containers/partitioned_vector/include/hpx/components/containers/partitioned_vector/partitioned_vector_decl.hpp
+++ b/components/containers/partitioned_vector/include/hpx/components/containers/partitioned_vector/partitioned_vector_decl.hpp
@@ -16,10 +16,12 @@
 #include <hpx/async_combinators/when_all.hpp>
 #include <hpx/components/client_base.hpp>
 #include <hpx/distribution_policies/container_distribution_policy.hpp>
-#include <hpx/modules/errors.hpp>
+#include <hpx/distribution_policies/explicit_container_distribution_policy.hpp>
+#include <hpx/functional/reference_wrapper.hpp>
 #include <hpx/runtime_components/distributed_metadata_base.hpp>
 #include <hpx/runtime_components/new.hpp>
 #include <hpx/runtime_distributed/copy_component.hpp>
+#include <hpx/type_support/identity.hpp>
 
 #include <hpx/components/containers/partitioned_vector/export_definitions.hpp>
 #include <hpx/components/containers/partitioned_vector/partitioned_vector_component_decl.hpp>
@@ -50,9 +52,10 @@ namespace hpx::server {
         {
             partition_data() = default;
 
-            partition_data(id_type const& part, std::size_t size,
-                std::uint32_t locality_id)
+            partition_data(id_type const& part, std::size_t first,
+                std::size_t size, std::uint32_t locality_id)
               : partition_(part)
+              , first_(first)
               , size_(size)
               , locality_id_(locality_id)
             {
@@ -64,6 +67,7 @@ namespace hpx::server {
             }
 
             hpx::id_type partition_;
+            std::size_t first_ = 0;
             std::size_t size_ = 0;
             std::uint32_t locality_id_ = naming::invalid_locality_id;
 
@@ -73,7 +77,9 @@ namespace hpx::server {
             template <typename Archive>
             void serialize(Archive& ar, unsigned)
             {
-                ar & partition_ & size_ & locality_id_;
+                // clang-format off
+                ar & partition_ & first_ & size_ & locality_id_;
+                // clang-format on
             }
         };
 
@@ -107,6 +113,7 @@ HPX_DISTRIBUTED_METADATA_DECLARATION(
 /// \endcond
 
 namespace hpx {
+
     /// hpx::partitioned_vector is a sequence container that encapsulates
     /// dynamic size arrays.
     ///
@@ -145,7 +152,7 @@ namespace hpx {
                 server::partitioned_vector_config_data>>
     {
     public:
-        using allocator_type = typename Data::allocator_type;
+        using allocator_type = detail::extract_allocator_type_t<T, Data>;
 
         using size_type = typename Data::size_type;
         using difference_type = typename Data::difference_type;
@@ -155,8 +162,8 @@ namespace hpx {
         using const_reference = T const;
 
 #if defined(HPX_NATIVE_MIC)
-        typedef T* pointer;
-        typedef T const* const_pointer;
+        using pointer = T*;
+        using const_pointer = T const*;
 #else
         using pointer = typename std::allocator_traits<allocator_type>::pointer;
         using const_pointer =
@@ -173,6 +180,8 @@ namespace hpx {
         using partitioned_vector_partition_client =
             hpx::partitioned_vector_partition<T, Data>;
 
+        using create_mode = traits::create_mode;
+
         struct partition_data
           : server::partitioned_vector_config_data::partition_data
         {
@@ -181,9 +190,9 @@ namespace hpx {
 
             partition_data() = default;
 
-            partition_data(id_type const& part, std::size_t size,
-                std::uint32_t locality_id)
-              : base_type(part, size, locality_id)
+            partition_data(id_type const& part, std::size_t first,
+                std::size_t size, std::uint32_t locality_id)
+              : base_type(part, first, size, locality_id)
             {
             }
 
@@ -200,8 +209,7 @@ namespace hpx {
         // size, and locality id.
         using partitions_vector_type = std::vector<partition_data>;
 
-        size_type size_;              // overall size of the vector
-        size_type partition_size_;    // cached partition size
+        size_type size_;    // overall size of the vector
 
         // This is the vector representing the base_index and corresponding
         // global ID's of the underlying partitioned_vector_partitions.
@@ -230,6 +238,8 @@ namespace hpx {
             segmented::local_segment_vector_iterator<T, Data,
                 typename partitions_vector_type::const_iterator>;
 
+        using partition_data_type = partition_data;
+
     private:
         friend class segmented::vector_iterator<T, Data>;
         friend class segmented::const_vector_iterator<T, Data>;
@@ -239,15 +249,15 @@ namespace hpx {
         friend class segmented::const_segment_vector_iterator<T, Data,
             typename partitions_vector_type::const_iterator>;
 
-        std::size_t get_partition_size() const;
-        std::size_t get_global_index(std::size_t segment, std::size_t part_size,
-            size_type local_index) const;
+        std::size_t get_partition_size(std::size_t partnum) const;
+        std::size_t get_global_index_part(
+            std::size_t partnum, size_type local_index) const;
 
         ///////////////////////////////////////////////////////////////////////
         // Connect this vector to the existing vector using the given symbolic
         // name.
         void get_data_helper(
-            id_type id, server::partitioned_vector_config_data data);
+            id_type id, server::partitioned_vector_config_data&& data);
 
         // this will be called by the base class once the registered id becomes
         // available
@@ -266,13 +276,13 @@ namespace hpx {
         partitioned_vector(future<id_type>&& f);
 
     public:
-        // Return the sequence number of the segment corresponding to the
-        // given global index
+        // Return the sequence number of the segment corresponding to the given
+        // global index
         std::size_t get_partition(size_type global_index) const;
 
-        // Return the local index inside the segment corresponding to the
-        // given global index
-        std::size_t get_local_index(size_type global_index) const;
+        // Return the local index inside the given segment
+        std::size_t get_local_index(
+            size_type partnum, size_type global_index) const;
 
         // Return the local indices inside the segment corresponding to the
         // given global indices
@@ -285,15 +295,8 @@ namespace hpx {
         std::size_t get_global_index(
             SegmentIter const& it, size_type local_index) const
         {
-            std::size_t part_size = partition_size_;
-            if (part_size == static_cast<std::size_t>(-1) || part_size == 0)
-                return size_;
-
-            std::size_t segment = it.base() - partitions_.cbegin();
-            if (segment == partitions_.size())
-                return size_;
-
-            return get_global_index(segment, part_size, local_index);
+            return get_global_index_part(
+                it.base() - partitions_.cbegin(), local_index);
         }
 
         template <typename SegmentIter>
@@ -308,8 +311,8 @@ namespace hpx {
         const_local_iterator get_const_local_iterator(
             size_type global_index) const;
 
-        // Return the segment iterator referencing a segment based on the
-        // given global index.
+        // Return the segment iterator referencing a segment based on the given
+        // global index.
         segment_iterator get_segment_iterator(size_type global_index);
         const_segment_iterator get_const_segment_iterator(
             size_type global_index) const;
@@ -322,19 +325,21 @@ namespace hpx {
 
         template <typename DistPolicy>
         static hpx::future<std::vector<bulk_locality_result>> create_helper1(
-            DistPolicy const& policy, std::size_t count, std::size_t size);
+            DistPolicy const& policy, std::size_t count,
+            std::vector<std::size_t> const& sizes, create_mode mode);
 
         template <typename DistPolicy>
         static hpx::future<std::vector<bulk_locality_result>> create_helper2(
-            DistPolicy const& policy, std::size_t count, std::size_t size,
-            T const& val);
+            DistPolicy const& policy, std::size_t count,
+            std::vector<std::size_t> const& sizes, T const& val);
 
         struct get_ptr_helper;
 
         // This function is called when we are creating the vector. It
         // initializes the partitions based on the give parameters.
         template <typename DistPolicy, typename Create>
-        void create(DistPolicy const& policy, Create&& creator);
+        void create(DistPolicy const& policy, Create&& creator,
+            create_mode mode = create_mode::resize);
 
         template <typename DistPolicy>
         void create(DistPolicy const& policy);
@@ -345,21 +350,46 @@ namespace hpx {
         // Perform a deep copy from the given vector
         void copy_from(partitioned_vector const& rhs);
 
+        enum class take_ref
+        {
+            yes = 0
+        };
+
+        partitioned_vector(partitioned_vector const& rhs, take_ref)
+          : base_type(rhs.get_id())
+          , size_(rhs.size_)
+        {
+        }
+
+        explicit partitioned_vector(hpx::id_type id, std::size_t size,
+            partitions_vector_type&& partitions)
+          : base_type(HPX_MOVE(id))
+          , size_(size)
+          , partitions_(partitions)
+        {
+        }
+
     public:
-        /// Default Constructor which create hpx::partitioned_vector with
+        static partitioned_vector create_from(hpx::id_type id, std::size_t size,
+            partitions_vector_type&& partitions)
+        {
+            return partitioned_vector(HPX_MOVE(id), size, HPX_MOVE(partitions));
+        }
+
+        /// Default Constructor which creates hpx::partitioned_vector with
         /// \a num_partitions = 0 and \a partition_size = 0. Hence, the overall
         /// size of the vector is 0.
         ///
         partitioned_vector();
 
-        /// Constructor which create hpx::partitioned_vector with the given
+        /// Constructor which creates hpx::partitioned_vector with the given
         /// overall \a size
         ///
         /// \param size             The overall size of the vector
         ///
         explicit partitioned_vector(size_type size);
 
-        /// Constructor which create and initialize vector with the given
+        /// Constructor which creates and initializes vector with the given
         /// \a where all elements are initialized with \a val.
         ///
         /// \param size             The overall size of the vector
@@ -369,8 +399,20 @@ namespace hpx {
         ///
         partitioned_vector(size_type size, T const& val);
 
-        /// Constructor which create and initialize vector of \a size using the
-        /// given distribution policy.
+        /// Constructor which creates vector of \a size using the given
+        /// distribution policy.
+        ///
+        /// \param policy           The distribution policy to use
+        /// \param symbolic_name    The (optional) name to register the newly
+        ///                         created vector
+        ///
+        template <typename DistPolicy>
+        explicit partitioned_vector(DistPolicy const& policy,
+            std::enable_if_t<traits::is_distribution_policy_v<DistPolicy>>* =
+                nullptr);
+
+        /// Constructor which creates and initializes vector of \a size using
+        /// the given distribution policy.
         ///
         /// \param size             The overall size of the vector
         /// \param policy           The distribution policy to use
@@ -379,12 +421,12 @@ namespace hpx {
         ///
         template <typename DistPolicy>
         partitioned_vector(size_type size, DistPolicy const& policy,
-            std::enable_if_t<
-                traits::is_distribution_policy<DistPolicy>::value>* = nullptr);
+            std::enable_if_t<traits::is_distribution_policy_v<DistPolicy>>* =
+                nullptr);
 
-        /// Constructor which create and initialize vector with the
-        /// given \a where all elements are initialized with \a val and
-        /// using the given distribution policy.
+        /// Constructor which creates and initializes vector of \a size, where
+        /// all elements are initialized with \a val and using the given
+        /// distribution policy.
         ///
         /// \param size             The overall size of the vector
         /// \param val              Default value for the elements in vector
@@ -395,8 +437,8 @@ namespace hpx {
         template <typename DistPolicy>
         partitioned_vector(size_type size, T const& val,
             DistPolicy const& policy,
-            std::enable_if_t<
-                traits::is_distribution_policy<DistPolicy>::value>* = nullptr);
+            std::enable_if_t<traits::is_distribution_policy_v<DistPolicy>>* =
+                nullptr);
 
         /// Copy construction performs a deep copy of the right hand side
         /// vector.
@@ -411,11 +453,9 @@ namespace hpx {
         partitioned_vector(partitioned_vector&& rhs) noexcept
           : base_type(HPX_MOVE(rhs))
           , size_(rhs.size_)
-          , partition_size_(rhs.partition_size_)
           , partitions_(HPX_MOVE(rhs.partitions_))
         {
             rhs.size_ = 0;
-            rhs.partition_size_ = static_cast<std::size_t>(-1);
         }
 
     public:
@@ -469,15 +509,19 @@ namespace hpx {
                 this->base_type::operator=(static_cast<base_type&&>(rhs));
 
                 size_ = rhs.size_;
-                partition_size_ = rhs.partition_size_;
                 partitions_ = HPX_MOVE(rhs.partitions_);
 
                 rhs.size_ = 0;
-                rhs.partition_size_ = static_cast<std::size_t>(-1);
             }
             return *this;
         }
 
+        // Create reference to rhs partitioned vector
+        partitioned_vector ref() const
+        {
+            return partitioned_vector(*this, take_ref::yes);
+        }
+
         ///////////////////////////////////////////////////////////////////////
         // Capacity related APIs in vector class
 
@@ -490,6 +534,15 @@ namespace hpx {
             return size_;
         }
 
+        /// \brief Compute the information about the underlying partitions.
+        ///
+        /// \return Return the partitions
+        ///
+        partitions_vector_type partitions() const
+        {
+            return partitions_;
+        }
+
         //
         //  Element access APIs in vector class
         //
@@ -503,8 +556,8 @@ namespace hpx {
         ///
         T get_value(launch::sync_policy, size_type pos) const
         {
-            return get_value(
-                launch::sync, get_partition(pos), get_local_index(pos));
+            auto part = get_partition(pos);
+            return get_value(launch::sync, part, get_local_index(part, pos));
         }
 
         /// Returns the element at position \a pos in the vector container.
@@ -519,7 +572,9 @@ namespace hpx {
         {
             partition_data const& part_data = partitions_[part];
             if (part_data.local_data_)
+            {
                 return part_data.local_data_->get_value(pos);
+            }
 
             return partitioned_vector_partition_client(part_data.partition_)
                 .get_value(launch::sync, pos);
@@ -535,7 +590,8 @@ namespace hpx {
         ///
         future<T> get_value(size_type pos) const
         {
-            return get_value(get_partition(pos), get_local_index(pos));
+            auto part = get_partition(pos);
+            return get_value(part, get_local_index(part, pos));
         }
 
         /// Returns the element at position \a pos in the given partition in
@@ -837,8 +893,9 @@ namespace hpx {
         template <typename T_>
         void set_value(launch::sync_policy, size_type pos, T_&& val)
         {
-            return set_value(launch::sync, get_partition(pos),
-                get_local_index(pos), HPX_FORWARD(T_, val));
+            auto part = get_partition(pos);
+            return set_value(launch::sync, part, get_local_index(part, pos),
+                HPX_FORWARD(T_, val));
         }
 
         /// Copy the value of \a val in the element at position \a pos in
@@ -876,8 +933,9 @@ namespace hpx {
         template <typename T_>
         future<void> set_value(size_type pos, T_&& val)
         {
+            auto part = get_partition(pos);
             return set_value(
-                get_partition(pos), get_local_index(pos), HPX_FORWARD(T_, val));
+                part, get_local_index(part, pos), HPX_FORWARD(T_, val));
         }
 
         /// Asynchronously set the element at position \a pos in
@@ -990,21 +1048,19 @@ namespace hpx {
 
                 // if the partition of the current position is NOT the same
                 // as the positions before the block ends here
-                else
-                {
-                    // this is the end of a block containing indexes ('pos')
-                    // of the same partition ('part').
-                    // set asynchronous values for this block
-                    part_futures.push_back(set_values(part_cur,
-                        get_local_indices(
-                            std::vector<size_type>(pos_block_begin, pos_it)),
-                        std::vector<T>(val_block_begin, val_it)));
-
-                    // reset block variables to start a new one from here
-                    part_cur = part;
-                    pos_block_begin = pos_it;
-                    val_block_begin = val_it;
-                }
+
+                // this is the end of a block containing indexes ('pos')
+                // of the same partition ('part').
+                // set asynchronous values for this block
+                part_futures.push_back(set_values(part_cur,
+                    get_local_indices(
+                        std::vector<size_type>(pos_block_begin, pos_it)),
+                    std::vector<T>(val_block_begin, val_it)));
+
+                // reset block variables to start a new one from here
+                part_cur = part;
+                pos_block_begin = pos_it;
+                val_block_begin = val_it;
             }
 
             // the end of the vector is also an end of a block
@@ -1023,6 +1079,38 @@ namespace hpx {
             return set_values(pos, val).get();
         }
 
+        template <typename F, typename... Ts>
+        future<util::invoke_result_t<F, T, Ts...>> apply_on(
+            size_type part, size_type pos, F f, Ts... ts) const
+        {
+            if (partitions_[part].local_data_)
+            {
+                return make_ready_future(partitions_[part].local_data_->apply(
+                    pos, HPX_FORWARD(F, f), HPX_FORWARD(Ts, ts)...));
+            }
+
+            return partitioned_vector_partition_client(
+                partitions_[part].partition_)
+                .apply(pos, HPX_FORWARD(F, f), HPX_FORWARD(Ts, ts)...);
+        }
+
+        template <typename F, typename... Ts>
+        auto apply(std::size_t pos, F f, Ts... ts)
+        {
+            auto part = get_partition(pos);
+            return apply_on(part, get_local_index(part, pos), HPX_FORWARD(F, f),
+                HPX_FORWARD(Ts, ts)...);
+        }
+
+        template <typename F, typename... Ts>
+        auto apply(launch::sync_policy, std::size_t pos, F f, Ts... ts)
+        {
+            auto part = get_partition(pos);
+            return apply_on(part, get_local_index(part, pos), HPX_FORWARD(F, f),
+                HPX_FORWARD(Ts, ts)...)
+                .get();
+        }
+
         // //CLEAR
         // // TODO if number of partitions is kept constant every time then
         // // clear should modify (clear each partitioned_vector_partition
@@ -1281,4 +1369,67 @@ namespace hpx {
             return segment_cend(naming::get_locality_id_from_id(id));
         }
     };
+
+    ///////////////////////////////////////////////////////////////////////////
+    template <typename T, typename Data>
+    struct reference_wrapper<partitioned_vector<T, Data>>
+    {
+        using wrapped_type = partitioned_vector<T, Data>;
+
+        // we define a default constructor to support serialization
+        reference_wrapper() = default;
+
+        // clang-format off
+        template <typename U,
+            typename Enable = std::enable_if_t<
+                !std::is_same_v<std::decay<U>, reference_wrapper>>>
+        // clang-format on
+        constexpr reference_wrapper(U&& val) noexcept
+          : ptr(val.ref())
+        {
+        }
+
+        reference_wrapper(reference_wrapper const& rhs)
+          : ptr(rhs.get().ref())
+        {
+        }
+        reference_wrapper(reference_wrapper&& rhs) = default;
+
+        reference_wrapper& operator=(reference_wrapper const& rhs)
+        {
+            ptr = rhs.get().ref();
+            return *this;
+        }
+        reference_wrapper& operator=(reference_wrapper&& rhs) = default;
+
+        constexpr operator wrapped_type&() noexcept
+        {
+            return ptr;
+        }
+
+        constexpr operator wrapped_type const&() const noexcept
+        {
+            return ptr;
+        }
+
+        [[nodiscard]] constexpr wrapped_type& get() noexcept
+        {
+            return ptr;
+        }
+
+        [[nodiscard]] constexpr wrapped_type const& get() const noexcept
+        {
+            return ptr;
+        }
+
+    private:
+        partitioned_vector<T, Data> ptr{};
+    };
+
+    template <typename T, typename Data>
+    reference_wrapper<partitioned_vector<T, Data>> ref(
+        partitioned_vector<T, Data>&& val) noexcept
+    {
+        return reference_wrapper<partitioned_vector<T, Data>>(HPX_MOVE(val));
+    }
 }    // namespace hpx
diff --git a/components/containers/partitioned_vector/include/hpx/components/containers/partitioned_vector/partitioned_vector_impl.hpp b/components/containers/partitioned_vector/include/hpx/components/containers/partitioned_vector/partitioned_vector_impl.hpp
index 74eea0a28318..69204f366b8d 100644
--- a/components/containers/partitioned_vector/include/hpx/components/containers/partitioned_vector/partitioned_vector_impl.hpp
+++ b/components/containers/partitioned_vector/include/hpx/components/containers/partitioned_vector/partitioned_vector_impl.hpp
@@ -14,7 +14,7 @@
 #include <hpx/async_combinators/wait_all.hpp>
 #include <hpx/components/get_ptr.hpp>
 #include <hpx/distribution_policies/container_distribution_policy.hpp>
-#include <hpx/functional/bind_back.hpp>
+#include <hpx/distribution_policies/explicit_container_distribution_policy.hpp>
 #include <hpx/modules/async_distributed.hpp>
 #include <hpx/modules/errors.hpp>
 #include <hpx/modules/execution.hpp>
@@ -42,24 +42,34 @@ namespace hpx {
 
     template <typename T, typename Data /*= std::vector<T> */>
     HPX_PARTITIONED_VECTOR_SPECIALIZATION_EXPORT std::size_t
-    partitioned_vector<T, Data>::get_partition_size() const
+    partitioned_vector<T, Data>::get_partition_size(std::size_t partnum) const
     {
-        std::size_t num_parts = partitions_.size();
-        return num_parts ? ((size_ + num_parts - 1) / num_parts) : 0;
+        std::size_t size = partitions_.size();
+        if (partnum == size)
+        {
+            return 0;
+        }
+        return size == 0 ? 0 : partitions_[partnum].size_;
     }
 
     template <typename T, typename Data /*= std::vector<T> */>
     HPX_PARTITIONED_VECTOR_SPECIALIZATION_EXPORT std::size_t
-    partitioned_vector<T, Data>::get_global_index(
-        std::size_t segment, std::size_t part_size, size_type local_index) const
+    partitioned_vector<T, Data>::get_global_index_part(
+        std::size_t partnum, size_type local_index) const
     {
-        return segment * part_size + local_index;
+        std::size_t size = partitions_.size();
+        if (partnum == size)
+        {
+            return size_;
+        }
+        return size == 0 ? local_index :
+                           partitions_[partnum].first_ + local_index;
     }
 
     template <typename T, typename Data /*= std::vector<T> */>
     HPX_PARTITIONED_VECTOR_SPECIALIZATION_EXPORT void
     partitioned_vector<T, Data>::get_data_helper(
-        id_type id, server::partitioned_vector_config_data data)
+        id_type id, server::partitioned_vector_config_data&& data)
     {
         partitions_.clear();
         partitions_.reserve(data.partitions_.size());
@@ -72,11 +82,9 @@ namespace hpx {
         std::vector<future<void>> ptrs;
         ptrs.reserve(partitions_.size());
 
-        using const_iterator = typename partitions_vector_type::const_iterator;
-
         std::size_t l = 0;
-        const_iterator end = partitions_.cend();
-        for (const_iterator it = partitions_.cbegin(); it != end; ++it, ++l)
+        auto end = partitions_.cend();
+        for (auto it = partitions_.cbegin(); it != end; ++it, ++l)
         {
             if (it->locality_id_ == this_locality)
             {
@@ -87,7 +95,6 @@ namespace hpx {
         }
         hpx::wait_all(ptrs);
 
-        partition_size_ = get_partition_size();
         this->base_type::reset(HPX_MOVE(id));
     }
 
@@ -175,29 +182,35 @@ namespace hpx {
     HPX_PARTITIONED_VECTOR_SPECIALIZATION_EXPORT std::size_t
     partitioned_vector<T, Data>::get_partition(size_type global_index) const
     {
+        if (global_index == 0)
+        {
+            return 0;
+        }
         if (global_index == size_)
+        {
             return partitions_.size();
+        }
 
-        std::size_t part_size = partition_size_;
-        if (part_size != 0)
-            return (part_size != size_) ? (global_index / part_size) : 0;
+        // find partition that holds the global index
+        for (std::size_t part = 0; part != partitions_.size(); ++part)
+        {
+            auto const& partition = partitions_[part];
+            if (partition.first_ <= global_index &&
+                global_index < partition.first_ + partition.size_)
+            {
+                return part;
+            }
+        }
 
         return partitions_.size();
     }
 
     template <typename T, typename Data /*= std::vector<T> */>
     HPX_PARTITIONED_VECTOR_SPECIALIZATION_EXPORT std::size_t
-    partitioned_vector<T, Data>::get_local_index(size_type global_index) const
+    partitioned_vector<T, Data>::get_local_index(
+        size_type partnum, size_type global_index) const
     {
-        if (global_index == size_ ||
-            partition_size_ == static_cast<std::size_t>(-1) ||
-            partition_size_ == 0)
-        {
-            return static_cast<std::size_t>(-1);
-        }
-
-        return (partition_size_ != size_) ? (global_index % partition_size_) :
-                                            global_index;
+        return global_index - partitions_[partnum].first_;
     }
 
     template <typename T, typename Data /*= std::vector<T> */>
@@ -207,7 +220,9 @@ namespace hpx {
             std::vector<size_type> indices) const
     {
         for (size_type& index : indices)
-            index = get_local_index(index);
+        {
+            index = get_local_index(get_partition(index), index);
+        }
         return indices;
     }
 
@@ -228,7 +243,7 @@ namespace hpx {
                 back.partition_, back.size_, back.local_data_);
         }
 
-        std::size_t local_index = get_local_index(global_index);
+        std::size_t local_index = get_local_index(part, global_index);
         HPX_ASSERT(local_index != static_cast<std::size_t>(-1));
 
         return local_iterator(partitions_[part].partition_, local_index,
@@ -252,7 +267,7 @@ namespace hpx {
                 back.partition_, back.size_, back.local_data_);
         }
 
-        std::size_t local_index = get_local_index(global_index);
+        std::size_t local_index = get_local_index(part, global_index);
         HPX_ASSERT(local_index != static_cast<std::size_t>(-1));
 
         return const_local_iterator(partitions_[part].partition_, local_index,
@@ -290,13 +305,15 @@ namespace hpx {
     template <typename DistPolicy>
     HPX_PARTITIONED_VECTOR_SPECIALIZATION_EXPORT hpx::future<
         std::vector<typename partitioned_vector<T, Data>::bulk_locality_result>>
-    partitioned_vector<T, Data>::create_helper1(
-        DistPolicy const& policy, std::size_t count, std::size_t size)
+    partitioned_vector<T, Data>::create_helper1(DistPolicy const& policy,
+        std::size_t count, std::vector<std::size_t> const& sizes,
+        create_mode mode)
     {
         using component_type =
             typename partitioned_vector_partition_client::server_component_type;
 
-        return policy.template bulk_create<component_type>(count, size);
+        return policy.template bulk_create<true, component_type>(
+            count, sizes, mode);
     }
 
     template <typename T, typename Data /*= std::vector<T> */>
@@ -304,12 +321,13 @@ namespace hpx {
     HPX_PARTITIONED_VECTOR_SPECIALIZATION_EXPORT hpx::future<
         std::vector<typename partitioned_vector<T, Data>::bulk_locality_result>>
     partitioned_vector<T, Data>::create_helper2(DistPolicy const& policy,
-        std::size_t count, std::size_t size, T const& val)
+        std::size_t count, std::vector<std::size_t> const& sizes, T const& val)
     {
         using component_type =
             typename partitioned_vector_partition_client::server_component_type;
 
-        return policy.template bulk_create<component_type>(count, size, val);
+        return policy.template bulk_create<true, component_type>(
+            count, sizes, val);
     }
 
     template <typename T, typename Data /*= std::vector<T> */>
@@ -329,18 +347,19 @@ namespace hpx {
     template <typename T, typename Data /*= std::vector<T> */>
     template <typename DistPolicy, typename Create>
     void partitioned_vector<T, Data>::create(
-        DistPolicy const& policy, Create&& creator)
+        DistPolicy const& policy, Create&& creator, create_mode mode)
     {
         std::size_t num_parts =
             traits::num_container_partitions<DistPolicy>::call(policy);
-        std::size_t part_size = (size_ + num_parts - 1) / num_parts;
+        std::vector<std::size_t> part_sizes =
+            traits::container_partition_sizes<DistPolicy>::call(policy, size_);
 
         // create as many partitions as required
         hpx::future<std::vector<bulk_locality_result>> f =
-            creator(policy, num_parts, part_size);
+            HPX_FORWARD(Create, creator)(policy, num_parts, part_sizes, mode);
 
         // now initialize our data structures
-        std::uint32_t this_locality = get_locality_id();
+        std::uint32_t const this_locality = get_locality_id();
         std::vector<future<void>> ptrs;
         ptrs.reserve(num_parts);
 
@@ -360,8 +379,9 @@ namespace hpx {
             for (hpx::id_type const& id : r.second)
             {
                 std::size_t size =
-                    (std::min)(part_size, size_ - allocated_size);
-                partitions_[l] = partition_data(id, size, locality);
+                    (std::min)(part_sizes[l], size_ - allocated_size);
+                partitions_[l] =
+                    partition_data(id, allocated_size, size, locality);
 
                 if (locality == this_locality)
                 {
@@ -377,7 +397,7 @@ namespace hpx {
                     HPX_ASSERT(allocated_size == size_);
 
                     // shrink last partition, if appropriate
-                    if (size != part_size)
+                    if (size != part_sizes.back())
                     {
                         partitioned_vector_partition_client(
                             partitions_[l - 1].partition_)
@@ -385,19 +405,14 @@ namespace hpx {
                     }
                     break;
                 }
-                else
-                {
-                    HPX_ASSERT(size == part_size);
-                }
+
+                HPX_ASSERT(size == part_sizes[l - 1]);
                 HPX_ASSERT(l < num_parts);
             }
         }
         HPX_ASSERT(l == num_parts);
 
         hpx::wait_all(ptrs);
-
-        // cache our partition size
-        partition_size_ = get_partition_size();
     }
 
     template <typename T, typename Data /*= std::vector<T> */>
@@ -405,7 +420,8 @@ namespace hpx {
     HPX_PARTITIONED_VECTOR_SPECIALIZATION_EXPORT void
     partitioned_vector<T, Data>::create(DistPolicy const& policy)
     {
-        create(policy, &partitioned_vector::create_helper1<DistPolicy>);
+        create(policy, &partitioned_vector::create_helper1<DistPolicy>,
+            traits::allocation_mode<DistPolicy>::call(policy));
     }
 
     template <typename T, typename Data /*= std::vector<T> */>
@@ -414,19 +430,21 @@ namespace hpx {
     partitioned_vector<T, Data>::create(T const& val, DistPolicy const& policy)
     {
         create(policy,
-            hpx::bind_back(&partitioned_vector::create_helper2<DistPolicy>,
-                std::ref(val)));
+            [&val](DistPolicy const& policy, std::size_t num_parts,
+                std::vector<std::size_t> const& part_sizes, create_mode) {
+                return create_helper2(policy, num_parts, part_sizes, val);
+            });
     }
 
     template <typename T, typename Data /*= std::vector<T> */>
     HPX_PARTITIONED_VECTOR_SPECIALIZATION_EXPORT void
     partitioned_vector<T, Data>::copy_from(partitioned_vector const& rhs)
     {
-        using const_iterator = typename partitions_vector_type::const_iterator;
-
         std::vector<future<id_type>> objs;
-        const_iterator end = rhs.partitions_.end();
-        for (const_iterator it = rhs.partitions_.begin(); it != end; ++it)
+        objs.reserve(rhs.partitions_.size());
+
+        auto end = rhs.partitions_.end();
+        for (auto it = rhs.partitions_.begin(); it != end; ++it)
         {
             using component_type =
                 typename partitioned_vector_partition_client::
@@ -445,12 +463,13 @@ namespace hpx {
         // to set the local partition data
         partitions_vector_type partitions;
         partitions.resize(rhs.partitions_.size());
+
         for (std::size_t i = 0; i != rhs.partitions_.size(); ++i)
         {
             std::uint32_t locality = rhs.partitions_[i].locality_id_;
 
-            partitions[i] = partition_data(
-                objs[i].get(), rhs.partitions_[i].size_, locality);
+            partitions[i] = partition_data(objs[i].get(),
+                rhs.partitions_[i].first_, rhs.partitions_[i].size_, locality);
 
             if (locality == this_locality)
             {
@@ -463,7 +482,6 @@ namespace hpx {
         hpx::wait_all(ptrs);
 
         size_ = rhs.size_;
-        partition_size_ = rhs.partition_size_;
         std::swap(partitions_, partitions);
     }
 
@@ -472,7 +490,6 @@ namespace hpx {
     HPX_PARTITIONED_VECTOR_SPECIALIZATION_EXPORT
     partitioned_vector<T, Data>::partitioned_vector()
       : size_(0)
-      , partition_size_(static_cast<std::size_t>(-1))
     {
     }
 
@@ -480,7 +497,6 @@ namespace hpx {
     HPX_PARTITIONED_VECTOR_SPECIALIZATION_EXPORT
     partitioned_vector<T, Data>::partitioned_vector(size_type size)
       : size_(size)
-      , partition_size_(static_cast<std::size_t>(-1))
     {
         if (size != 0)
             create(hpx::container_layout);
@@ -491,7 +507,6 @@ namespace hpx {
     partitioned_vector<T, Data>::partitioned_vector(
         size_type size, T const& val)
       : size_(size)
-      , partition_size_(static_cast<std::size_t>(-1))
     {
         if (size != 0)
             create(val, hpx::container_layout);
@@ -502,23 +517,31 @@ namespace hpx {
     HPX_PARTITIONED_VECTOR_SPECIALIZATION_EXPORT
     partitioned_vector<T, Data>::partitioned_vector(size_type size,
         DistPolicy const& policy,
-        std::enable_if_t<traits::is_distribution_policy<DistPolicy>::value>*)
+        std::enable_if_t<traits::is_distribution_policy_v<DistPolicy>>*)
       : size_(size)
-      , partition_size_(static_cast<std::size_t>(-1))
     {
         if (size != 0)
             create(policy);
     }
 
+    template <typename T, typename Data /*= std::vector<T> */>
+    template <typename DistPolicy>
+    HPX_PARTITIONED_VECTOR_SPECIALIZATION_EXPORT
+    partitioned_vector<T, Data>::partitioned_vector(DistPolicy const& policy,
+        std::enable_if_t<traits::is_distribution_policy_v<DistPolicy>>*)
+      : size_(0)
+    {
+        reserve(policy);
+    }
+
     template <typename T, typename Data /*= std::vector<T> */>
     template <typename DistPolicy>
     HPX_PARTITIONED_VECTOR_SPECIALIZATION_EXPORT
     partitioned_vector<T, Data>::partitioned_vector(size_type size,
         T const& val, DistPolicy const& policy,
         std::enable_if_t<
-            traits::is_distribution_policy<DistPolicy>::value>* /*= nullptr*/)
+            traits::is_distribution_policy_v<DistPolicy>>* /*= nullptr*/)
       : size_(size)
-      , partition_size_(static_cast<std::size_t>(-1))
     {
         if (size != 0)
             create(val, policy);
diff --git a/components/containers/partitioned_vector/include/hpx/components/containers/partitioned_vector/partitioned_vector_predef.hpp b/components/containers/partitioned_vector/include/hpx/components/containers/partitioned_vector/partitioned_vector_predef.hpp
index 7a821d7d777d..a6e12f45278b 100644
--- a/components/containers/partitioned_vector/include/hpx/components/containers/partitioned_vector/partitioned_vector_predef.hpp
+++ b/components/containers/partitioned_vector/include/hpx/components/containers/partitioned_vector/partitioned_vector_predef.hpp
@@ -1,5 +1,5 @@
 //  Copyright (c) 2014 Anuj R. Sharma
-//  Copyright (c) 2014-2016 Hartmut Kaiser
+//  Copyright (c) 2014-2024 Hartmut Kaiser
 //
 //  SPDX-License-Identifier: BSL-1.0
 //  Distributed under the Boost Software License, Version 1.0. (See accompanying
@@ -8,6 +8,7 @@
 #pragma once
 
 #include <hpx/distribution_policies/container_distribution_policy.hpp>
+#include <hpx/distribution_policies/explicit_container_distribution_policy.hpp>
 
 #include <hpx/components/containers/partitioned_vector/export_definitions.hpp>
 #include <hpx/components/containers/partitioned_vector/partitioned_vector_component_decl.hpp>
@@ -36,6 +37,12 @@ extern template hpx::partitioned_vector<double,
 extern template hpx::partitioned_vector<double,
     std::vector<double>>::partitioned_vector(size_type, double const&,
     hpx::container_distribution_policy const&, void*);
+extern template hpx::partitioned_vector<double,
+    std::vector<double>>::partitioned_vector(size_type,
+    hpx::explicit_container_distribution_policy const&, void*);
+extern template hpx::partitioned_vector<double,
+    std::vector<double>>::partitioned_vector(size_type, double const&,
+    hpx::explicit_container_distribution_policy const&, void*);
 
 // partitioned_vector<int>
 HPX_REGISTER_PARTITIONED_VECTOR_DECLARATION(int)
@@ -49,9 +56,15 @@ extern template hpx::partitioned_vector<int,
 extern template hpx::partitioned_vector<int,
     std::vector<int>>::partitioned_vector(size_type, int const&,
     hpx::container_distribution_policy const&, void*);
+extern template hpx::partitioned_vector<int,
+    std::vector<int>>::partitioned_vector(size_type,
+    hpx::explicit_container_distribution_policy const&, void*);
+extern template hpx::partitioned_vector<int,
+    std::vector<int>>::partitioned_vector(size_type, int const&,
+    hpx::explicit_container_distribution_policy const&, void*);
 
 // partitioned_vector<long long>
-typedef long long long_long;
+using long_long = long long;
 HPX_REGISTER_PARTITIONED_VECTOR_DECLARATION(long_long)
 
 extern template class hpx::server::partitioned_vector<long long,
@@ -66,6 +79,12 @@ extern template hpx::partitioned_vector<long long,
 extern template hpx::partitioned_vector<long long,
     std::vector<long long>>::partitioned_vector(size_type, long long const&,
     hpx::container_distribution_policy const&, void*);
+extern template hpx::partitioned_vector<long long,
+    std::vector<long long>>::partitioned_vector(size_type,
+    hpx::explicit_container_distribution_policy const&, void*);
+extern template hpx::partitioned_vector<long long,
+    std::vector<long long>>::partitioned_vector(size_type, long long const&,
+    hpx::explicit_container_distribution_policy const&, void*);
 
 // partitioned_vector<std::string>
 using partitioned_vector_std_string_argument = std::string;
@@ -85,5 +104,11 @@ extern template hpx::partitioned_vector<std::string,
 extern template hpx::partitioned_vector<std::string,
     std::vector<std::string>>::partitioned_vector(size_type, std::string const&,
     hpx::container_distribution_policy const&, void*);
+extern template hpx::partitioned_vector<std::string,
+    std::vector<std::string>>::partitioned_vector(size_type,
+    hpx::explicit_container_distribution_policy const&, void*);
+extern template hpx::partitioned_vector<std::string,
+    std::vector<std::string>>::partitioned_vector(size_type, std::string const&,
+    hpx::explicit_container_distribution_policy const&, void*);
 
 #endif
diff --git a/components/containers/partitioned_vector/include/hpx/components/containers/partitioned_vector/partitioned_vector_segmented_iterator.hpp b/components/containers/partitioned_vector/include/hpx/components/containers/partitioned_vector/partitioned_vector_segmented_iterator.hpp
index d9b192f48c04..00b7d7915842 100644
--- a/components/containers/partitioned_vector/include/hpx/components/containers/partitioned_vector/partitioned_vector_segmented_iterator.hpp
+++ b/components/containers/partitioned_vector/include/hpx/components/containers/partitioned_vector/partitioned_vector_segmented_iterator.hpp
@@ -54,9 +54,9 @@ namespace hpx::segmented {
         local_raw_vector_iterator() = default;
 
         local_raw_vector_iterator(base_iterator const& it,
-            std::shared_ptr<server::partitioned_vector<T, Data>> const& data)
+            std::shared_ptr<server::partitioned_vector<T, Data>> data)
           : base_type(it)
-          , data_(data)
+          , data_(HPX_MOVE(data))
         {
         }
 
@@ -102,9 +102,9 @@ namespace hpx::segmented {
         const_local_raw_vector_iterator() = default;
 
         const_local_raw_vector_iterator(base_iterator const& it,
-            std::shared_ptr<server::partitioned_vector<T, Data>> const& data)
+            std::shared_ptr<server::partitioned_vector<T, Data>> data)
           : base_type(it)
-          , data_(data)
+          , data_(HPX_MOVE(data))
         {
         }
 
@@ -144,6 +144,16 @@ namespace hpx::segmented {
             {
             }
 
+            local_vector_value_proxy(local_vector_value_proxy const&) = default;
+            local_vector_value_proxy(local_vector_value_proxy&&) = default;
+
+            local_vector_value_proxy& operator=(
+                local_vector_value_proxy const&) = default;
+            local_vector_value_proxy& operator=(
+                local_vector_value_proxy&&) = default;
+
+            ~local_vector_value_proxy() = default;
+
             operator T() const
             {
                 if (!it_.get_data())
@@ -172,6 +182,7 @@ namespace hpx::segmented {
                 return *this;
             }
 
+        private:
             local_vector_iterator<T, Data> const& it_;
         };
 
@@ -184,6 +195,18 @@ namespace hpx::segmented {
             {
             }
 
+            const_local_vector_value_proxy(
+                const_local_vector_value_proxy const&) = default;
+            const_local_vector_value_proxy(
+                const_local_vector_value_proxy&&) = default;
+
+            const_local_vector_value_proxy& operator=(
+                const_local_vector_value_proxy const&) = default;
+            const_local_vector_value_proxy& operator=(
+                const_local_vector_value_proxy&&) = default;
+
+            ~const_local_vector_value_proxy() = default;
+
             operator T() const
             {
                 if (!it_.get_data())
@@ -194,6 +217,7 @@ namespace hpx::segmented {
                 return *it_.local();
             }
 
+        private:
             const_local_vector_iterator<T, Data> const& it_;
         };
 
@@ -202,15 +226,23 @@ namespace hpx::segmented {
         struct vector_value_proxy
         {
             explicit vector_value_proxy(
-                hpx::partitioned_vector<T, Data>& v, std::size_t index)
-              : v_(v)
+                hpx::partitioned_vector<T, Data>& v, std::size_t const index)
+              : v_(&v)
               , index_(index)
             {
             }
 
+            vector_value_proxy(vector_value_proxy const&) = default;
+            vector_value_proxy(vector_value_proxy&&) = default;
+
+            vector_value_proxy& operator=(vector_value_proxy const&) = default;
+            vector_value_proxy& operator=(vector_value_proxy&&) = default;
+
+            ~vector_value_proxy() = default;
+
             operator T() const
             {
-                return v_.get_value(launch::sync, index_);
+                return v_->get_value(launch::sync, index_);
             }
 
             template <typename T_,
@@ -218,11 +250,12 @@ namespace hpx::segmented {
                     !std::is_same_v<std::decay_t<T_>, vector_value_proxy>>>
             vector_value_proxy& operator=(T_&& value)
             {
-                v_.set_value(launch::sync, index_, HPX_FORWARD(T_, value));
+                v_->set_value(launch::sync, index_, HPX_FORWARD(T_, value));
                 return *this;
             }
 
-            partitioned_vector<T, Data>& v_;
+        private:
+            partitioned_vector<T, Data>* v_;
             std::size_t index_;
         };
     }    // namespace detail
@@ -246,27 +279,24 @@ namespace hpx::segmented {
         using size_type = std::size_t;
 
         // constructors
-        local_vector_iterator()
-          : partition_()
-          , local_index_(static_cast<size_type>(-1))
-        {
-        }
+        local_vector_iterator() = default;
 
-        local_vector_iterator(hpx::id_type const& partition,
-            size_type local_index,
-            std::shared_ptr<server::partitioned_vector<T, Data>> const& data)
-          : partition_(partitioned_vector_partition<T, Data>(partition))
+        local_vector_iterator(hpx::id_type partition,
+            size_type const local_index,
+            std::shared_ptr<server::partitioned_vector<T, Data>> data)
+          : partition_(
+                partitioned_vector_partition<T, Data>(HPX_MOVE(partition)))
           , local_index_(local_index)
-          , data_(data)
+          , data_(HPX_MOVE(data))
         {
         }
 
         local_vector_iterator(partitioned_vector_partition<T, Data> partition,
-            size_type local_index,
-            std::shared_ptr<server::partitioned_vector<T, Data>> const& data)
-          : partition_(partition)
+            size_type const local_index,
+            std::shared_ptr<server::partitioned_vector<T, Data>> data) noexcept
+          : partition_(HPX_MOVE(partition))
           , local_index_(local_index)
-          , data_(data)
+          , data_(HPX_MOVE(data))
         {
         }
 
@@ -280,14 +310,18 @@ namespace hpx::segmented {
         local_raw_iterator local()
         {
             if (partition_ && !data_)
+            {
                 data_ = partition_.get_ptr();
+            }
             return local_raw_iterator(
                 data_->begin() + local_index_, data_);    //-V522
         }
         local_raw_const_iterator local() const
         {
             if (partition_ && !data_)
+            {
                 data_ = partition_.get_ptr();
+            }
             return local_raw_iterator(
                 data_->cbegin() + local_index_, data_);    //-V522
         }
@@ -296,18 +330,11 @@ namespace hpx::segmented {
         friend class hpx::serialization::access;
 
         template <typename Archive>
-        void load(Archive& ar, unsigned /* version */)
-        {
-            ar & partition_ & local_index_;
-        }
-        template <typename Archive>
-        void save(Archive& ar, unsigned /* version */) const
+        void serialize(Archive& ar, unsigned /* version */)
         {
             ar & partition_ & local_index_;
         }
 
-        HPX_SERIALIZATION_SPLIT_MEMBER()
-
     protected:
         friend class hpx::util::iterator_core_access;
 
@@ -322,38 +349,39 @@ namespace hpx::segmented {
             return segmented::detail::local_vector_value_proxy<T, Data>(*this);
         }
 
-        void increment()
+        void increment() noexcept
         {
             ++local_index_;
         }
 
-        void decrement()
+        void decrement() noexcept
         {
             --local_index_;
         }
 
-        void advance(std::ptrdiff_t n)
+        void advance(std::ptrdiff_t const n) noexcept
         {
             local_index_ += n;
         }
 
-        std::ptrdiff_t distance_to(local_vector_iterator const& other) const
+        std::ptrdiff_t distance_to(
+            local_vector_iterator const& other) const noexcept
         {
             HPX_ASSERT(partition_ == other.partition_);
             return other.local_index_ - local_index_;
         }
 
     public:
-        partitioned_vector_partition<T, Data>& get_partition()
+        partitioned_vector_partition<T, Data>& get_partition() noexcept
         {
             return partition_;
         }
-        partitioned_vector_partition<T, Data> get_partition() const
+        partitioned_vector_partition<T, Data> get_partition() const noexcept
         {
             return partition_;
         }
 
-        size_type get_local_index() const
+        [[nodiscard]] size_type get_local_index() const noexcept
         {
             return local_index_;
         }
@@ -361,26 +389,30 @@ namespace hpx::segmented {
         std::shared_ptr<server::partitioned_vector<T, Data>>& get_data()
         {
             if (partition_ && !data_)
+            {
                 data_ = partition_.get_ptr();
+            }
             return data_;
         }
         std::shared_ptr<server::partitioned_vector<T, Data>> const& get_data()
             const
         {
             if (partition_ && !data_)
+            {
                 data_ = partition_.get_ptr();
+            }
             return data_;
         }
 
     protected:
         // refer to a partition of the vector
-        partitioned_vector_partition<T, Data> partition_;
+        partitioned_vector_partition<T, Data> partition_{};
 
         // local position in the referenced partition
-        size_type local_index_;
+        size_type local_index_ = static_cast<size_type>(-1);
 
         // caching address of component
-        mutable std::shared_ptr<server::partitioned_vector<T, Data>> data_;
+        mutable std::shared_ptr<server::partitioned_vector<T, Data>> data_{};
     };
 
     template <typename T, typename Data>
@@ -389,7 +421,6 @@ namespace hpx::segmented {
             T const, std::random_access_iterator_tag,
             segmented::detail::const_local_vector_value_proxy<T, Data>>
     {
-    private:
         using base_type =
             hpx::util::iterator_facade<const_local_vector_iterator<T, Data>,
                 T const, std::random_access_iterator_tag,
@@ -399,28 +430,25 @@ namespace hpx::segmented {
         using size_type = std::size_t;
 
         // constructors
-        const_local_vector_iterator()
-          : partition_()
-          , local_index_(static_cast<size_type>(-1))
-        {
-        }
+        const_local_vector_iterator() = default;
 
-        const_local_vector_iterator(hpx::id_type const& partition,
-            size_type local_index,
-            std::shared_ptr<server::partitioned_vector<T, Data>> const& data)
-          : partition_(partitioned_vector_partition<T, Data>(partition))
+        const_local_vector_iterator(hpx::id_type partition,
+            size_type const local_index,
+            std::shared_ptr<server::partitioned_vector<T, Data>> data)
+          : partition_(
+                partitioned_vector_partition<T, Data>(HPX_MOVE(partition)))
           , local_index_(local_index)
-          , data_(data)
+          , data_(HPX_MOVE(data))
         {
         }
 
         const_local_vector_iterator(
             partitioned_vector_partition<T, Data> partition,
-            size_type local_index,
-            std::shared_ptr<server::partitioned_vector<T, Data>> const& data)
-          : partition_(partition)
+            size_type const local_index,
+            std::shared_ptr<server::partitioned_vector<T, Data>> data) noexcept
+          : partition_(HPX_MOVE(partition))
           , local_index_(local_index)
-          , data_(data)
+          , data_(HPX_MOVE(data))
         {
         }
 
@@ -439,14 +467,18 @@ namespace hpx::segmented {
         local_raw_iterator local()
         {
             if (partition_ && !data_)
+            {
                 data_ = partition_.get_ptr();
+            }
             return local_raw_iterator(
                 data_->cbegin() + local_index_, data_);    //-V522
         }
         local_raw_const_iterator local() const
         {
             if (partition_ && !data_)
+            {
                 data_ = partition_.get_ptr();
+            }
             return local_raw_const_iterator(
                 data_->cbegin() + local_index_, data_);    //-V522
         }
@@ -455,17 +487,10 @@ namespace hpx::segmented {
         friend class hpx::serialization::access;
 
         template <typename Archive>
-        void load(Archive& ar, unsigned /* version */)
+        void serialize(Archive& ar, unsigned /* version */)
         {
             ar & partition_ & local_index_;
         }
-        template <typename Archive>
-        void save(Archive& ar, unsigned /* version */) const
-        {
-            ar & partition_ & local_index_;
-        }
-
-        HPX_SERIALIZATION_SPLIT_MEMBER()
 
     protected:
         friend class hpx::util::iterator_core_access;
@@ -482,34 +507,34 @@ namespace hpx::segmented {
                 *this);
         }
 
-        void increment()
+        void increment() noexcept
         {
             ++local_index_;
         }
 
-        void decrement()
+        void decrement() noexcept
         {
             --local_index_;
         }
 
-        void advance(std::ptrdiff_t n)
+        void advance(std::ptrdiff_t const n) noexcept
         {
             local_index_ += n;
         }
 
         std::ptrdiff_t distance_to(
-            const_local_vector_iterator const& other) const
+            const_local_vector_iterator const& other) const noexcept
         {
             HPX_ASSERT(partition_ == other.partition_);
             return other.local_index_ - local_index_;
         }
 
     public:
-        partitioned_vector_partition<T, Data> const& get_partition() const
+        partitioned_vector_partition<T, Data> get_partition() const
         {
             return partition_;
         }
-        size_type get_local_index() const
+        [[nodiscard]] size_type get_local_index() const noexcept
         {
             return local_index_;
         }
@@ -517,26 +542,30 @@ namespace hpx::segmented {
         std::shared_ptr<server::partitioned_vector<T, Data>>& get_data()
         {
             if (partition_ && !data_)
+            {
                 data_ = partition_.get_ptr();
+            }
             return data_;
         }
         std::shared_ptr<server::partitioned_vector<T, Data>> const& get_data()
             const
         {
             if (partition_ && !data_)
+            {
                 data_ = partition_.get_ptr();
+            }
             return data_;
         }
 
     protected:
         // refer to a partition of the vector
-        partitioned_vector_partition<T, Data> partition_;
+        partitioned_vector_partition<T, Data> partition_{};
 
         // local position in the referenced partition
-        size_type local_index_;
+        size_type local_index_ = static_cast<size_type>(-1);
 
         // caching address of component
-        mutable std::shared_ptr<server::partitioned_vector<T, Data>> data_;
+        mutable std::shared_ptr<server::partitioned_vector<T, Data>> data_{};
     };
 
     ///////////////////////////////////////////////////////////////////////////
@@ -552,10 +581,7 @@ namespace hpx::segmented {
             segment_vector_iterator<T, Data, BaseIter>, BaseIter>;
 
     public:
-        segment_vector_iterator()
-          : data_(nullptr)
-        {
-        }
+        segment_vector_iterator() = default;
 
         explicit segment_vector_iterator(
             BaseIter const& it, partitioned_vector<T, Data>* data = nullptr)
@@ -564,11 +590,12 @@ namespace hpx::segmented {
         {
         }
 
-        partitioned_vector<T, Data>* get_data()
+        [[nodiscard]] partitioned_vector<T, Data>* get_data() noexcept
         {
             return data_;
         }
-        partitioned_vector<T, Data> const* get_data() const
+        [[nodiscard]] partitioned_vector<T, Data> const* get_data()
+            const noexcept
         {
             return data_;
         }
@@ -580,7 +607,7 @@ namespace hpx::segmented {
         }
 
     private:
-        partitioned_vector<T, Data>* data_;
+        partitioned_vector<T, Data>* data_ = nullptr;
     };
 
     template <typename T, typename Data, typename BaseIter>
@@ -593,10 +620,7 @@ namespace hpx::segmented {
             const_segment_vector_iterator<T, Data, BaseIter>, BaseIter>;
 
     public:
-        const_segment_vector_iterator()
-          : data_(nullptr)
-        {
-        }
+        const_segment_vector_iterator() = default;
 
         template <typename RightBaseIter>
         explicit const_segment_vector_iterator(
@@ -613,7 +637,8 @@ namespace hpx::segmented {
         {
         }
 
-        partitioned_vector<T, Data> const* get_data() const
+        [[nodiscard]] partitioned_vector<T, Data> const* get_data()
+            const noexcept
         {
             return data_;
         }
@@ -625,11 +650,12 @@ namespace hpx::segmented {
         }
 
     private:
-        partitioned_vector<T, Data> const* data_;
+        partitioned_vector<T, Data> const* data_ = nullptr;
     };
 
     ///////////////////////////////////////////////////////////////////////////
     namespace detail {
+
         template <typename BaseIterator>
         struct is_requested_locality
         {
@@ -637,12 +663,12 @@ namespace hpx::segmented {
                 typename std::iterator_traits<BaseIterator>::reference;
 
             explicit is_requested_locality(
-                std::uint32_t locality_id = naming::invalid_locality_id)
+                std::uint32_t const locality_id = naming::invalid_locality_id)
               : locality_id_(locality_id)
             {
             }
 
-            bool operator()(reference val) const
+            constexpr bool operator()(reference val) const
             {
                 return locality_id_ == naming::invalid_locality_id ||
                     locality_id_ == val.locality_id_;
@@ -694,12 +720,18 @@ namespace hpx::segmented {
         void unsatisfy_predicate()
         {
             while (this->base() != end_ && predicate_(*this->base()))
+            {
                 ++(this->base_reference());
+            }
 
             if (this->base() != end_)
+            {
                 data_ = this->base()->local_data_;
+            }
             else
+            {
                 data_.reset();
+            }
         }
 
     private:
@@ -716,9 +748,13 @@ namespace hpx::segmented {
             ++(this->base_reference());
 
             if (this->base() != end_)
+            {
                 data_ = this->base()->local_data_;
+            }
             else
+            {
                 data_.reset();
+            }
         }
 
         void satisfy_predicate()
@@ -727,9 +763,13 @@ namespace hpx::segmented {
                 ++(this->base_reference());
 
             if (this->base() != end_)
+            {
                 data_ = this->base()->local_data_;
+            }
             else
+            {
                 data_.reset();
+            }
         }
 
         std::shared_ptr<server::partitioned_vector<T, Data>> data_;
@@ -759,30 +799,30 @@ namespace hpx::segmented {
         using local_iterator =
             typename partitioned_vector<T, Data>::local_iterator;
 
+        // disable use of brackets_proxy in iterator_facade
+        using use_brackets_proxy = std::false_type;
+
         // constructors
-        vector_iterator()
-          : data_(nullptr)
-          , global_index_(static_cast<size_type>(-1))
-        {
-        }
+        vector_iterator() = default;
 
-        vector_iterator(
-            partitioned_vector<T, Data>* data, size_type global_index)
+        vector_iterator(partitioned_vector<T, Data>* data,
+            size_type const global_index) noexcept
           : data_(data)
           , global_index_(global_index)
         {
         }
 
-        partitioned_vector<T, Data>* get_data()
+        [[nodiscard]] partitioned_vector<T, Data>* get_data() noexcept
         {
             return data_;
         }
-        partitioned_vector<T, Data> const* get_data() const
+        [[nodiscard]] partitioned_vector<T, Data> const* get_data()
+            const noexcept
         {
             return data_;
         }
 
-        size_type get_global_index() const
+        [[nodiscard]] size_type get_global_index() const noexcept
         {
             return global_index_;
         }
@@ -802,25 +842,25 @@ namespace hpx::segmented {
                 *data_, global_index_);
         }
 
-        void increment()
+        void increment() noexcept
         {
             HPX_ASSERT(data_);
             ++global_index_;
         }
 
-        void decrement()
+        void decrement() noexcept
         {
             HPX_ASSERT(data_);
             --global_index_;
         }
 
-        void advance(std::ptrdiff_t n)
+        void advance(std::ptrdiff_t const n) noexcept
         {
             HPX_ASSERT(data_);
             global_index_ += n;
         }
 
-        std::ptrdiff_t distance_to(vector_iterator const& other) const
+        std::ptrdiff_t distance_to(vector_iterator const& other) const noexcept
         {
             HPX_ASSERT(data_ && other.data_);
             HPX_ASSERT(data_ == other.data_);
@@ -828,10 +868,10 @@ namespace hpx::segmented {
         }
 
         // refer to the vector
-        partitioned_vector<T, Data>* data_;
+        partitioned_vector<T, Data>* data_ = nullptr;
 
         // global position in the referenced vector
-        size_type global_index_;
+        size_type global_index_ = static_cast<size_type>(-1);
     };
 
     ///////////////////////////////////////////////////////////////////////////
@@ -853,25 +893,24 @@ namespace hpx::segmented {
         using local_iterator =
             typename partitioned_vector<T, Data>::const_local_iterator;
 
+        // disable use of brackets_proxy in iterator_facade
+        using use_brackets_proxy = std::false_type;
+
         // constructors
-        const_vector_iterator()
-          : data_(nullptr)
-          , global_index_(static_cast<size_type>(-1))
-        {
-        }
+        const_vector_iterator() = default;
 
-        const_vector_iterator(
-            partitioned_vector<T, Data> const* data, size_type global_index)
+        const_vector_iterator(partitioned_vector<T, Data> const* data,
+            size_type const global_index) noexcept
           : data_(data)
           , global_index_(global_index)
         {
         }
 
-        partitioned_vector<T, Data> const* get_data() const
+        partitioned_vector<T, Data> const* get_data() const noexcept
         {
             return data_;
         }
-        size_type get_global_index() const
+        [[nodiscard]] size_type get_global_index() const noexcept
         {
             return global_index_;
         }
@@ -879,7 +918,7 @@ namespace hpx::segmented {
     protected:
         friend class hpx::util::iterator_core_access;
 
-        bool equal(const_vector_iterator const& other) const
+        bool equal(const_vector_iterator const& other) const noexcept
         {
             return data_ == other.data_ && global_index_ == other.global_index_;
         }
@@ -890,25 +929,26 @@ namespace hpx::segmented {
             return data_->get_value(launch::sync, global_index_);
         }
 
-        void increment()
+        void increment() noexcept
         {
             HPX_ASSERT(data_);
             ++global_index_;
         }
 
-        void decrement()
+        void decrement() noexcept
         {
             HPX_ASSERT(data_);
             --global_index_;
         }
 
-        void advance(std::ptrdiff_t n)
+        void advance(std::ptrdiff_t const n)
         {
             HPX_ASSERT(data_);
             global_index_ += n;
         }
 
-        std::ptrdiff_t distance_to(const_vector_iterator const& other) const
+        std::ptrdiff_t distance_to(
+            const_vector_iterator const& other) const noexcept
         {
             HPX_ASSERT(data_ && other.data_);
             HPX_ASSERT(data_ == other.data_);
@@ -916,10 +956,10 @@ namespace hpx::segmented {
         }
 
         // refer to the vector
-        partitioned_vector<T, Data> const* data_;
+        partitioned_vector<T, Data> const* data_ = nullptr;
 
         // global position in the referenced vector
-        size_type global_index_;
+        size_type global_index_ = static_cast<size_type>(-1);
     };
 }    // namespace hpx::segmented
 
@@ -985,7 +1025,9 @@ namespace hpx::traits {
         static local_iterator end(segment_iterator seg_iter)
         {
             if (seg_iter.is_at_end())
+            {
                 --seg_iter;    // return iterator to the end of last segment
+            }
 
             auto& base = seg_iter.base();
             return local_iterator(
@@ -1076,7 +1118,9 @@ namespace hpx::traits {
         static local_iterator end(segment_iterator seg_iter)
         {
             if (seg_iter.is_at_end())
+            {
                 --seg_iter;    // return iterator to the end of last segment
+            }
 
             auto& base = seg_iter.base();
             return local_iterator(
diff --git a/components/containers/partitioned_vector/include/hpx/components/containers/partitioned_vector/serialization/partitioned_vector.hpp b/components/containers/partitioned_vector/include/hpx/components/containers/partitioned_vector/serialization/partitioned_vector.hpp
new file mode 100644
index 000000000000..1aa5cadb44fc
--- /dev/null
+++ b/components/containers/partitioned_vector/include/hpx/components/containers/partitioned_vector/serialization/partitioned_vector.hpp
@@ -0,0 +1,119 @@
+//  Copyright (c) 2017 Christopher Taylor
+//  Copyright (c) 2024 Hartmut Kaiser
+//
+//  SPDX-License-Identifier: BSL-1.0
+//  Distributed under the Boost Software License, Version 1.0. (See accompanying
+//  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#pragma once
+
+#include <hpx/config.hpp>
+#include <hpx/components/containers/partitioned_vector/partitioned_vector_decl.hpp>
+#include <hpx/serialization/serialize.hpp>
+
+#include <cstddef>
+#include <string>
+#include <vector>
+
+namespace hpx::serialization {
+
+    template <typename T, typename Data>
+    void serialize(
+        input_archive& ar, hpx::partitioned_vector<T, Data>& v, unsigned)
+    {
+        using partitioned_vector = hpx::partitioned_vector<T, Data>;
+        bool has_id = false;
+        ar >> has_id;
+        if (has_id)
+        {
+            hpx::id_type id;
+            std::size_t size;
+            std::vector<typename partitioned_vector::partition_data_type>
+                partitions;
+
+            ar >> id >> size >> partitions;
+            v = partitioned_vector::create_from(
+                HPX_MOVE(id), size, HPX_MOVE(partitions));
+        }
+        else
+        {
+            std::string registered_name;
+            ar >> registered_name;
+            v.connect_to(registered_name).get();
+        }
+    }
+
+    template <typename T, typename Data>
+    void serialize(
+        output_archive& ar, hpx::partitioned_vector<T, Data> const& v, unsigned)
+    {
+        bool has_id = v.valid();
+        ar << has_id;
+        if (has_id)
+        {
+            ar << v.get_id() << v.size() << v.partitions();
+        }
+        else
+        {
+            std::string const registered_name = v.registered_name();
+            if (registered_name.empty())
+            {
+                HPX_THROW_EXCEPTION(hpx::error::invalid_status,
+                    "hpx::serialization::serialize",
+                    "partitioned_vector is not registered");
+            }
+            ar << registered_name;
+        }
+    }
+
+    template <typename T, typename Data>
+    void serialize(input_archive& ar,
+        hpx::reference_wrapper<hpx::partitioned_vector<T, Data>>& v, unsigned)
+    {
+        using partitioned_vector = hpx::partitioned_vector<T, Data>;
+
+        bool has_id = false;
+        ar >> has_id;
+        if (has_id)
+        {
+            hpx::id_type id;
+            std::size_t size;
+            std::vector<typename partitioned_vector::partition_data_type>
+                partitions;
+
+            ar >> id >> size >> partitions;
+            v = hpx::ref(partitioned_vector::create_from(
+                HPX_MOVE(id), size, HPX_MOVE(partitions)));
+        }
+        else
+        {
+            std::string registered_name;
+            ar >> registered_name;
+            v.get().connect_to(registered_name).get();
+        }
+    }
+
+    template <typename T, typename Data>
+    void serialize(output_archive& ar,
+        hpx::reference_wrapper<hpx::partitioned_vector<T, Data>> const& v,
+        unsigned)
+    {
+        bool has_id = v.get().valid();
+        ar << has_id;
+        if (has_id)
+        {
+            ar << v.get().get_id() << v.get().size() << v.get().partitions();
+        }
+        else
+        {
+            std::string const registered_name = v.get().registered_name();
+            if (registered_name.empty())
+            {
+                HPX_THROW_EXCEPTION(hpx::error::invalid_status,
+                    "hpx::serialization::serialize",
+                    "partitioned_vector is not registered");
+            }
+            ar << registered_name;
+        }
+    }
+}    // namespace hpx::serialization
diff --git a/components/containers/partitioned_vector/include/hpx/include/partitioned_vector.hpp b/components/containers/partitioned_vector/include/hpx/include/partitioned_vector.hpp
index 4796f62341cd..674202b95962 100644
--- a/components/containers/partitioned_vector/include/hpx/include/partitioned_vector.hpp
+++ b/components/containers/partitioned_vector/include/hpx/include/partitioned_vector.hpp
@@ -7,6 +7,4 @@
 #pragma once
 
 #include <hpx/components/containers/partitioned_vector/partitioned_vector.hpp>
-
-
-
+#include <hpx/components/containers/partitioned_vector/serialization/partitioned_vector.hpp>
diff --git a/components/containers/partitioned_vector/include/hpx/include/partitioned_vector_predef.hpp b/components/containers/partitioned_vector/include/hpx/include/partitioned_vector_predef.hpp
index a56793514efc..069f15fbc40c 100644
--- a/components/containers/partitioned_vector/include/hpx/include/partitioned_vector_predef.hpp
+++ b/components/containers/partitioned_vector/include/hpx/include/partitioned_vector_predef.hpp
@@ -1,4 +1,4 @@
-//  Copyright (C) 2017 Hartmut Kaiser
+//  Copyright (C) 2017-2024 Hartmut Kaiser
 //
 //  SPDX-License-Identifier: BSL-1.0
 //  Distributed under the Boost Software License, Version 1.0. (See accompanying
@@ -7,6 +7,4 @@
 #pragma once
 
 #include <hpx/components/containers/partitioned_vector/partitioned_vector_predef.hpp>
-
-
-
+#include <hpx/components/containers/partitioned_vector/serialization/partitioned_vector.hpp>
diff --git a/components/containers/partitioned_vector/include/hpx/runtime/serialization/partitioned_vector.hpp b/components/containers/partitioned_vector/include/hpx/runtime/serialization/partitioned_vector.hpp
deleted file mode 100644
index 0e940b5ec974..000000000000
--- a/components/containers/partitioned_vector/include/hpx/runtime/serialization/partitioned_vector.hpp
+++ /dev/null
@@ -1,39 +0,0 @@
-//  Copyright (c) 2017 Christopher Taylor
-//
-//  SPDX-License-Identifier: BSL-1.0
-//  Distributed under the Boost Software License, Version 1.0. (See accompanying
-//  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
-
-#pragma once
-
-#include <hpx/config.hpp>
-#include <hpx/components/containers/partitioned_vector/partitioned_vector_decl.hpp>
-#include <hpx/modules/errors.hpp>
-#include <hpx/serialization/serialize.hpp>
-
-#include <string>
-
-namespace hpx::serialization {
-
-    template <typename T>
-    void serialize(input_archive& ar, hpx::partitioned_vector<T>& v, unsigned)
-    {
-        std::string pvec_registered_name;
-        ar >> pvec_registered_name;
-        v.connect_to(pvec_registered_name).get();
-    }
-
-    template <typename T>
-    void serialize(
-        output_archive& ar, const hpx::partitioned_vector<T>& v, unsigned)
-    {
-        std::string pvec_registered_name = v.registered_name();
-        if (pvec_registered_name.empty())
-        {
-            HPX_THROW_EXCEPTION(hpx::error::invalid_status,
-                "hpx::serialization::serialize",
-                "partitioned_vector is not registered");
-        }
-        ar << pvec_registered_name;
-    }
-}    // namespace hpx::serialization
diff --git a/components/containers/partitioned_vector/src/partitioned_vector_component_double.cpp b/components/containers/partitioned_vector/src/partitioned_vector_component_double.cpp
index b08b3882435b..a52c32f359d4 100644
--- a/components/containers/partitioned_vector/src/partitioned_vector_component_double.cpp
+++ b/components/containers/partitioned_vector/src/partitioned_vector_component_double.cpp
@@ -8,6 +8,7 @@
 
 #if !defined(HPX_HAVE_STATIC_LINKING)
 #include <hpx/distribution_policies/container_distribution_policy.hpp>
+#include <hpx/distribution_policies/explicit_container_distribution_policy.hpp>
 
 #include <hpx/components/containers/partitioned_vector/export_definitions.hpp>
 #include <hpx/components/containers/partitioned_vector/partitioned_vector.hpp>
@@ -36,6 +37,12 @@ hpx::partitioned_vector<double, std::vector<double>>::partitioned_vector(
 template HPX_PARTITIONED_VECTOR_EXPORT
 hpx::partitioned_vector<double, std::vector<double>>::partitioned_vector(
     size_type, double const&, hpx::container_distribution_policy const&, void*);
+template HPX_PARTITIONED_VECTOR_EXPORT
+hpx::partitioned_vector<double, std::vector<double>>::partitioned_vector(
+    size_type, hpx::explicit_container_distribution_policy const&, void*);
+template HPX_PARTITIONED_VECTOR_EXPORT hpx::partitioned_vector<double,
+    std::vector<double>>::partitioned_vector(size_type, double const&,
+    hpx::explicit_container_distribution_policy const&, void*);
 
 #if defined(HPX_MSVC)
 #pragma warning(pop)
diff --git a/components/containers/partitioned_vector/src/partitioned_vector_component_int.cpp b/components/containers/partitioned_vector/src/partitioned_vector_component_int.cpp
index 1dc775086ee3..1d47be48a633 100644
--- a/components/containers/partitioned_vector/src/partitioned_vector_component_int.cpp
+++ b/components/containers/partitioned_vector/src/partitioned_vector_component_int.cpp
@@ -8,6 +8,7 @@
 
 #if !defined(HPX_HAVE_STATIC_LINKING)
 #include <hpx/distribution_policies/container_distribution_policy.hpp>
+#include <hpx/distribution_policies/explicit_container_distribution_policy.hpp>
 
 #include <hpx/components/containers/partitioned_vector/export_definitions.hpp>
 #include <hpx/components/containers/partitioned_vector/partitioned_vector.hpp>
@@ -38,6 +39,12 @@ hpx::partitioned_vector<int, std::vector<int>>::partitioned_vector(
 template HPX_PARTITIONED_VECTOR_EXPORT
 hpx::partitioned_vector<int, std::vector<int>>::partitioned_vector(
     size_type, int const&, hpx::container_distribution_policy const&, void*);
+template HPX_PARTITIONED_VECTOR_EXPORT
+hpx::partitioned_vector<int, std::vector<int>>::partitioned_vector(
+    size_type, hpx::explicit_container_distribution_policy const&, void*);
+template HPX_PARTITIONED_VECTOR_EXPORT
+hpx::partitioned_vector<int, std::vector<int>>::partitioned_vector(
+    size_type, int const&, hpx::explicit_container_distribution_policy const&, void*);
 
 template class HPX_PARTITIONED_VECTOR_EXPORT
     hpx::server::partitioned_vector<long long, std::vector<long long>>;
@@ -51,6 +58,12 @@ hpx::partitioned_vector<long long, std::vector<long long>>::partitioned_vector(
 template HPX_PARTITIONED_VECTOR_EXPORT hpx::partitioned_vector<long long,
     std::vector<long long>>::partitioned_vector(size_type, long long const&,
     hpx::container_distribution_policy const&, void*);
+template HPX_PARTITIONED_VECTOR_EXPORT
+hpx::partitioned_vector<long long, std::vector<long long>>::partitioned_vector(
+    size_type, hpx::explicit_container_distribution_policy const&, void*);
+template HPX_PARTITIONED_VECTOR_EXPORT hpx::partitioned_vector<long long,
+    std::vector<long long>>::partitioned_vector(size_type, long long const&,
+    hpx::explicit_container_distribution_policy const&, void*);
 
 #if defined(HPX_MSVC)
 #pragma warning(pop)
diff --git a/components/containers/partitioned_vector/src/partitioned_vector_component_std_string.cpp b/components/containers/partitioned_vector/src/partitioned_vector_component_std_string.cpp
index 8c32b90404e9..d74d531fd58b 100644
--- a/components/containers/partitioned_vector/src/partitioned_vector_component_std_string.cpp
+++ b/components/containers/partitioned_vector/src/partitioned_vector_component_std_string.cpp
@@ -8,6 +8,7 @@
 
 #if !defined(HPX_HAVE_STATIC_LINKING)
 #include <hpx/distribution_policies/container_distribution_policy.hpp>
+#include <hpx/distribution_policies/explicit_container_distribution_policy.hpp>
 
 #include <hpx/components/containers/partitioned_vector/export_definitions.hpp>
 #include <hpx/components/containers/partitioned_vector/partitioned_vector.hpp>
@@ -39,6 +40,12 @@ template HPX_PARTITIONED_VECTOR_EXPORT hpx::partitioned_vector<std::string,
 template HPX_PARTITIONED_VECTOR_EXPORT hpx::partitioned_vector<std::string,
     std::vector<std::string>>::partitioned_vector(size_type, std::string const&,
     hpx::container_distribution_policy const&, void*);
+template HPX_PARTITIONED_VECTOR_EXPORT hpx::partitioned_vector<std::string,
+    std::vector<std::string>>::partitioned_vector(size_type,
+    hpx::explicit_container_distribution_policy const&, void*);
+template HPX_PARTITIONED_VECTOR_EXPORT hpx::partitioned_vector<std::string,
+    std::vector<std::string>>::partitioned_vector(size_type, std::string const&,
+    hpx::explicit_container_distribution_policy const&, void*);
 
 #if defined(HPX_MSVC)
 #pragma warning(pop)
diff --git a/components/containers/partitioned_vector/tests/unit/serialization_partitioned_vector.cpp b/components/containers/partitioned_vector/tests/unit/serialization_partitioned_vector.cpp
index 2723a8c4d5af..66d5ba705eb4 100644
--- a/components/containers/partitioned_vector/tests/unit/serialization_partitioned_vector.cpp
+++ b/components/containers/partitioned_vector/tests/unit/serialization_partitioned_vector.cpp
@@ -10,9 +10,10 @@
 
 #include <hpx/include/parallel_fill.hpp>
 #include <hpx/include/partitioned_vector.hpp>
-#include <hpx/runtime/serialization/partitioned_vector.hpp>
 
 #include <hpx/modules/testing.hpp>
+#include <hpx/naming/detail/preprocess_gid_types.hpp>
+#include <hpx/serialization/detail/preprocess_container.hpp>
 
 #include <cstddef>
 #include <numeric>
@@ -24,7 +25,7 @@
 HPX_REGISTER_PARTITIONED_VECTOR(double)
 #endif
 
-typedef unsigned long ulong;
+using ulong = unsigned long;
 
 HPX_REGISTER_PARTITIONED_VECTOR(ulong)
 HPX_REGISTER_PARTITIONED_VECTOR(long)
@@ -36,15 +37,28 @@ void test(T minval, T maxval)
     {
         std::vector<char> buffer;
 
-        hpx::serialization::output_archive oarchive(
-            buffer, hpx::serialization::archive_flags::disable_data_chunking);
-
         std::size_t sz = static_cast<std::size_t>(maxval - minval);
 
         hpx::partitioned_vector<T> os(sz);
         os.register_as("test_vector");
         hpx::fill(hpx::execution::par, std::begin(os), std::end(os), 42);
 
+        hpx::serialization::detail::preprocess_container gather_size;
+        hpx::serialization::output_archive archive(gather_size,
+            hpx::serialization::archive_flags::disable_data_chunking);
+
+        auto& split_gids = archive.get_extra_data<
+            hpx::serialization::detail::preprocess_gid_types>();
+
+        archive << os;
+
+        hpx::serialization::output_archive oarchive(
+            buffer, hpx::serialization::archive_flags::disable_data_chunking);
+
+        auto& osplit_gids = oarchive.get_extra_data<
+            hpx::serialization::detail::preprocess_gid_types>();
+        osplit_gids.set_split_gids(split_gids.move_split_gids());
+
         oarchive << os;
 
         hpx::serialization::input_archive iarchive(buffer);
@@ -88,4 +102,5 @@ int main()
 
     return hpx::util::report_errors();
 }
+
 #endif
diff --git a/components/containers/unordered/include/hpx/components/containers/unordered/unordered_map.hpp b/components/containers/unordered/include/hpx/components/containers/unordered/unordered_map.hpp
index 03f4b4753489..a37ccfd26f54 100644
--- a/components/containers/unordered/include/hpx/components/containers/unordered/unordered_map.hpp
+++ b/components/containers/unordered/include/hpx/components/containers/unordered/unordered_map.hpp
@@ -435,7 +435,7 @@ namespace hpx {
 
             // create as many partitions as required
             hpx::future<std::vector<bulk_locality_result>> f =
-                policy.template bulk_create<component_type>(num_parts);
+                policy.template bulk_create<false, component_type>(num_parts);
 
             // now initialize our data structures
             init(f.get());
@@ -454,7 +454,7 @@ namespace hpx {
 
             // create as many partitions as required
             hpx::future<std::vector<bulk_locality_result>> f =
-                policy.template bulk_create<component_type>(
+                policy.template bulk_create<false, component_type>(
                     num_parts, bucket_count, hash, equal);
 
             // now initialize our data structures
diff --git a/libs/core/datastructures/include/hpx/datastructures/member_pack.hpp b/libs/core/datastructures/include/hpx/datastructures/member_pack.hpp
index b74cb60e8469..22ae32c6345c 100644
--- a/libs/core/datastructures/include/hpx/datastructures/member_pack.hpp
+++ b/libs/core/datastructures/include/hpx/datastructures/member_pack.hpp
@@ -50,7 +50,7 @@ namespace hpx::util {
         }
 #else
         template <std::size_t I, typename T,
-            bool Empty = std::is_empty<T>::value && !std::is_final<T>::value>
+            bool Empty = std::is_empty_v<T> && !std::is_final_v<T>>
         struct member_leaf
         {
             T member;
diff --git a/libs/core/functional/CMakeLists.txt b/libs/core/functional/CMakeLists.txt
index c37d19e05e8c..e10b492a16b9 100644
--- a/libs/core/functional/CMakeLists.txt
+++ b/libs/core/functional/CMakeLists.txt
@@ -33,6 +33,7 @@ set(functional_headers
     hpx/functional/experimental/scope_exit.hpp
     hpx/functional/experimental/scope_fail.hpp
     hpx/functional/experimental/scope_success.hpp
+    hpx/functional/reference_wrapper.hpp
     hpx/functional/serialization/detail/serializable_basic_function.hpp
     hpx/functional/serialization/detail/vtable/serializable_function_vtable.hpp
     hpx/functional/serialization/detail/vtable/serializable_vtable.hpp
diff --git a/libs/core/functional/include/hpx/functional/reference_wrapper.hpp b/libs/core/functional/include/hpx/functional/reference_wrapper.hpp
new file mode 100644
index 000000000000..e10a150dd66a
--- /dev/null
+++ b/libs/core/functional/include/hpx/functional/reference_wrapper.hpp
@@ -0,0 +1,60 @@
+//  Copyright (c) 2024 Hartmut Kaiser
+//
+//  SPDX-License-Identifier: BSL-1.0
+//  Distributed under the Boost Software License, Version 1.0. (See accompanying
+//  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+/// \file reference_wrapper.hpp
+/// \page hpx::reference_wrapper, hpx::ref, hpx::cref
+/// \headerfile hpx/functional.hpp
+
+#pragma once
+
+#include <hpx/config.hpp>
+
+#include <functional>
+
+namespace hpx {
+
+    ///////////////////////////////////////////////////////////////////////////
+    template <typename T>
+    struct reference_wrapper : std::reference_wrapper<T>
+    {
+        reference_wrapper() = delete;
+
+        using std::reference_wrapper<T>::referrence_wrapper;
+    };
+
+    template <typename T>
+    [[nodiscard]] constexpr reference_wrapper<T> ref(T& val) noexcept
+    {
+        return reference_wrapper<T>(val);
+    }
+
+    template <typename T>
+    void ref(T const&&) = delete;
+
+    template <typename T>
+    [[nodiscard]] constexpr reference_wrapper<T> ref(
+        reference_wrapper<T> val) noexcept
+    {
+        return val;
+    }
+
+    template <typename T>
+    [[nodiscard]] constexpr reference_wrapper<T const> cref(
+        T const& val) noexcept
+    {
+        return reference_wrapper<T const>(val);
+    }
+
+    template <typename T>
+    void cref(T const&&) = delete;
+
+    template <typename T>
+    [[nodiscard]] constexpr reference_wrapper<T const> cref(
+        reference_wrapper<T> val) noexcept
+    {
+        return val;
+    }
+}    // namespace hpx
diff --git a/libs/core/iterator_support/include/hpx/iterator_support/iterator_facade.hpp b/libs/core/iterator_support/include/hpx/iterator_support/iterator_facade.hpp
index 2769e209c3a0..a60c1c71070a 100644
--- a/libs/core/iterator_support/include/hpx/iterator_support/iterator_facade.hpp
+++ b/libs/core/iterator_support/include/hpx/iterator_support/iterator_facade.hpp
@@ -14,6 +14,8 @@
 #pragma once
 
 #include <hpx/config.hpp>
+
+#include <hpx/concepts/has_xxx.hpp>
 #include <hpx/iterator_support/traits/is_iterator.hpp>
 #include <hpx/type_support/equality.hpp>
 
@@ -233,7 +235,7 @@ namespace hpx::util {
         // Implementation for random access iterators
 
         // A proxy return type for operator[], needed to deal with iterators
-        // that may invalidate referents upon destruction. Consider the
+        // that may invalidate references upon destruction. Consider the
         // temporary iterator in *(a + n)
         template <typename Iterator>
         class operator_brackets_proxy
@@ -267,22 +269,34 @@ namespace hpx::util {
             Iterator iter_;
         };
 
+        // We can force (not) using the operator_brackets_proxy by adding an
+        // embedded type use_brackets_proxy to the iterator that evaluates to
+        // either std::true_type of std::false_type.
+        HPX_HAS_XXX_TRAIT_DEF(use_brackets_proxy)
+
         // A meta-function that determines whether operator[] must return a
         // proxy, or whether it can simply return a copy of the value_type.
-        template <typename ValueType>
+        template <typename Iterator, typename Value, typename Enable = void>
         struct use_operator_brackets_proxy
           : std::integral_constant<bool,
-                !(std::is_copy_constructible_v<ValueType> &&
-                    std::is_const_v<ValueType>)>
+                !(std::is_copy_constructible_v<Value> &&
+                    std::is_const_v<Value>)>
+        {
+        };
+
+        template <typename Iterator, typename Value>
+        struct use_operator_brackets_proxy<Iterator, Value,
+            std::enable_if_t<has_use_brackets_proxy_v<Iterator>>>
+          : Iterator::use_brackets_proxy
         {
         };
 
         template <typename Iterator, typename Value>
         struct operator_brackets_result
         {
-            using type =
-                std::conditional_t<use_operator_brackets_proxy<Value>::value,
-                    operator_brackets_proxy<Iterator>, Value>;
+            using type = std::conditional_t<
+                use_operator_brackets_proxy<Iterator, Value>::value,
+                operator_brackets_proxy<Iterator>, Value>;
         };
 
         template <typename Iterator>
@@ -319,11 +333,9 @@ namespace hpx::util {
 
             HPX_HOST_DEVICE iterator_facade_base() = default;
 
-            HPX_HOST_DEVICE constexpr
-                typename operator_brackets_result<Derived, T>::type
-                operator[](difference_type n) const
+            HPX_HOST_DEVICE constexpr auto operator[](difference_type n) const
             {
-                using use_proxy = use_operator_brackets_proxy<T>;
+                using use_proxy = use_operator_brackets_proxy<Derived, T>;
 
                 return make_operator_brackets_result<Derived>(
                     this->derived() + n, use_proxy{});
diff --git a/libs/core/testing/src/performance.cpp b/libs/core/testing/src/performance.cpp
index 0227a776785a..6b2369157844 100644
--- a/libs/core/testing/src/performance.cpp
+++ b/libs/core/testing/src/performance.cpp
@@ -46,7 +46,7 @@ namespace hpx::util {
         char const* nanobench_hpx_simple_template() noexcept
         {
             return R"DELIM(Results:
-{{#result}}        
+{{#result}}
 name: {{name}},
 executor: {{context(executor)}},
 average: {{average(elapsed)}}{{^-last}}
@@ -238,7 +238,7 @@ average: {{average(elapsed)}}{{^-last}}
         using timer = std::chrono::high_resolution_clock;
         for (std::size_t i = 0; i != steps; ++i)
         {
-            // For now we don't flush the cache
+            // For now, we don't flush the cache
             //flush_cache();
             timer::time_point start = timer::now();
             test();
diff --git a/libs/full/actions_base/include/hpx/actions_base/component_action.hpp b/libs/full/actions_base/include/hpx/actions_base/component_action.hpp
index 1680bc423b79..66530481847b 100644
--- a/libs/full/actions_base/include/hpx/actions_base/component_action.hpp
+++ b/libs/full/actions_base/include/hpx/actions_base/component_action.hpp
@@ -297,7 +297,8 @@ namespace hpx::actions {
       : hpx::actions::make_direct_action_t<decltype(&component::func),         \
             &component::func, name>                                            \
     {                                                                          \
-    }; /**/
+    };                                                                         \
+    /**/
 
 #define HPX_DEFINE_COMPONENT_DIRECT_ACTION_2(component, func)                  \
     HPX_DEFINE_COMPONENT_DIRECT_ACTION_3(                                      \
diff --git a/libs/full/actions_base/include/hpx/actions_base/traits/is_distribution_policy.hpp b/libs/full/actions_base/include/hpx/actions_base/traits/is_distribution_policy.hpp
index d6b96358a7b0..73f989755c54 100644
--- a/libs/full/actions_base/include/hpx/actions_base/traits/is_distribution_policy.hpp
+++ b/libs/full/actions_base/include/hpx/actions_base/traits/is_distribution_policy.hpp
@@ -9,6 +9,7 @@
 
 #include <cstddef>
 #include <type_traits>
+#include <vector>
 
 namespace hpx::traits {
 
@@ -31,4 +32,35 @@ namespace hpx::traits {
             return policy.get_num_localities();
         }
     };
+
+    // By default, the sizes of the partitions are equal across the localities
+    // represented by the given distribution policy.
+    template <typename Policy, typename Enable = void>
+    struct container_partition_sizes
+    {
+        static std::vector<std::size_t> call(
+            Policy const& policy, std::size_t const size)
+        {
+            std::size_t const num_parts = policy.get_num_partitions();
+            return std::vector<std::size_t>(
+                num_parts, (size + num_parts - 1) / num_parts);
+        }
+    };
+
+    // By default, the container distribution policy resizes the underlying
+    // vectors.
+    enum class create_mode
+    {
+        resize = 0,
+        reserve = 1
+    };
+
+    template <typename Policy, typename Enable = void>
+    struct allocation_mode
+    {
+        static create_mode call(Policy const&)
+        {
+            return create_mode::resize;
+        }
+    };
 }    // namespace hpx::traits
diff --git a/libs/full/async_distributed/include/hpx/async_distributed/transfer_continuation_action.hpp b/libs/full/async_distributed/include/hpx/async_distributed/transfer_continuation_action.hpp
index 7cd7ed742ad3..32c7af2067bb 100644
--- a/libs/full/async_distributed/include/hpx/async_distributed/transfer_continuation_action.hpp
+++ b/libs/full/async_distributed/include/hpx/async_distributed/transfer_continuation_action.hpp
@@ -257,16 +257,14 @@ namespace hpx::actions {
         {
             // If this is a direct action and deferred schedule was requested,
             // i.e. if we are not the last parcel, return immediately
-            if (base_type::direct_execution::value)
+            if constexpr (base_type::direct_execution::value)
             {
                 return;
             }
-            else
-            {
-                // If this is not a direct action, we can safely set deferred_schedule
-                // to false
-                deferred_schedule = false;
-            }
+
+            // If this is not a direct action, we can safely set
+            // deferred_schedule to false
+            deferred_schedule = false;
         }
 
         schedule_thread(HPX_MOVE(target), lva, comptype, num_thread);
diff --git a/libs/full/compute/include/hpx/compute/host/target_distribution_policy.hpp b/libs/full/compute/include/hpx/compute/host/target_distribution_policy.hpp
index 8537fc4ac8b6..f3f7842f3398 100644
--- a/libs/full/compute/include/hpx/compute/host/target_distribution_policy.hpp
+++ b/libs/full/compute/include/hpx/compute/host/target_distribution_policy.hpp
@@ -142,7 +142,7 @@ namespace hpx::compute::host {
         /// \returns A future holding the list of global addresses which
         ///          represent the newly created objects
         ///
-        template <typename Component, typename... Ts>
+        template <bool WithCount, typename Component, typename... Ts>
         hpx::future<std::vector<bulk_locality_result>> bulk_create(
             [[maybe_unused]] std::size_t count,
             [[maybe_unused]] Ts&&... ts) const
@@ -183,8 +183,9 @@ namespace hpx::compute::host {
                 }
 
                 objs.push_back(
-                    components::bulk_create_async<Component>(localities.back(),
-                        num_partitions, ts..., HPX_MOVE(local_targets)));
+                    components::bulk_create_async<WithCount, Component>(
+                        localities.back(), num_partitions, ts...,
+                        HPX_MOVE(local_targets)));
             }
 
             return hpx::dataflow(
diff --git a/libs/full/distribution_policies/CMakeLists.txt b/libs/full/distribution_policies/CMakeLists.txt
index d681132a6cb5..72812cd1bd40 100644
--- a/libs/full/distribution_policies/CMakeLists.txt
+++ b/libs/full/distribution_policies/CMakeLists.txt
@@ -15,6 +15,7 @@ set(distribution_policies_headers
     hpx/distribution_policies/colocating_distribution_policy.hpp
     hpx/distribution_policies/container_distribution_policy.hpp
     hpx/distribution_policies/default_distribution_policy.hpp
+    hpx/distribution_policies/explicit_container_distribution_policy.hpp
     hpx/distribution_policies/target_distribution_policy.hpp
     hpx/distribution_policies/unwrapping_result_policy.hpp
 )
diff --git a/libs/full/distribution_policies/include/hpx/distribution_policies/binpacking_distribution_policy.hpp b/libs/full/distribution_policies/include/hpx/distribution_policies/binpacking_distribution_policy.hpp
index 1f76904a3771..d0a8025ff8f8 100644
--- a/libs/full/distribution_policies/include/hpx/distribution_policies/binpacking_distribution_policy.hpp
+++ b/libs/full/distribution_policies/include/hpx/distribution_policies/binpacking_distribution_policy.hpp
@@ -79,7 +79,7 @@ namespace hpx::components {
             std::vector<hpx::id_type> const& localities_;
         };
 
-        template <typename Component>
+        template <bool WithCount, typename Component>
         struct create_bulk_helper
         {
             typedef std::pair<hpx::id_type, std::vector<hpx::id_type>>
@@ -104,7 +104,7 @@ namespace hpx::components {
 
                 for (std::size_t i = 0; i != to_create.size(); ++i)
                 {
-                    objs.emplace_back(bulk_create_async<Component>(
+                    objs.emplace_back(bulk_create_async<WithCount, Component>(
                         localities_[i], to_create[i], vs...));
                 }
 
@@ -269,7 +269,7 @@ namespace hpx::components {
         /// \returns A future holding the list of global addresses which
         ///          represent the newly created objects
         ///
-        template <typename Component, typename... Ts>
+        template <bool WithCount, typename Component, typename... Ts>
         hpx::future<std::vector<bulk_locality_result>> bulk_create(
             std::size_t count, Ts&&... vs) const
         {
@@ -281,8 +281,9 @@ namespace hpx::components {
                         counter_name_, localities_);
 
                 return values.then(hpx::bind_back(
-                    detail::create_bulk_helper<Component>(localities_), count,
-                    HPX_FORWARD(Ts, vs)...));
+                    detail::create_bulk_helper<WithCount, Component>(
+                        localities_),
+                    count, HPX_FORWARD(Ts, vs)...));
             }
 
             // handle special cases
@@ -291,7 +292,8 @@ namespace hpx::components {
                 localities_.front();
 
             hpx::future<std::vector<hpx::id_type>> f =
-                bulk_create_async<Component>(id, count, HPX_FORWARD(Ts, vs)...);
+                bulk_create_async<WithCount, Component>(
+                    id, count, HPX_FORWARD(Ts, vs)...);
 
             return f.then(hpx::launch::sync,
                 [id = HPX_MOVE(id)](hpx::future<std::vector<hpx::id_type>>&& f)
diff --git a/libs/full/distribution_policies/include/hpx/distribution_policies/colocating_distribution_policy.hpp b/libs/full/distribution_policies/include/hpx/distribution_policies/colocating_distribution_policy.hpp
index ec526faca6a6..12ff0dea6a30 100644
--- a/libs/full/distribution_policies/include/hpx/distribution_policies/colocating_distribution_policy.hpp
+++ b/libs/full/distribution_policies/include/hpx/distribution_policies/colocating_distribution_policy.hpp
@@ -1,4 +1,4 @@
-//  Copyright (c) 2014-2023 Hartmut Kaiser
+//  Copyright (c) 2014-2024 Hartmut Kaiser
 //
 //  SPDX-License-Identifier: BSL-1.0
 //  Distributed under the Boost Software License, Version 1.0. (See accompanying
@@ -39,7 +39,6 @@ namespace hpx::components {
     /// object is currently placed.
     struct colocating_distribution_policy
     {
-    public:
         /// Default-construct a new instance of a \a colocating_distribution_policy.
         /// This policy will represent the local locality.
         constexpr colocating_distribution_policy() = default;
@@ -89,6 +88,13 @@ namespace hpx::components {
                     naming::get_id_from_locality_id(agas::get_locality_id()),
                     HPX_FORWARD(Ts, vs)...);
             }
+            if (!naming::detail::is_migratable(id_.get_gid()))
+            {
+                return create_async<Component>(
+                    naming::get_id_from_locality_id(
+                        naming::get_locality_id_from_id(id_)),
+                    HPX_FORWARD(Ts, vs)...);
+            }
             return create_colocated_async<Component>(
                 id_, HPX_FORWARD(Ts, vs)...);
         }
@@ -111,7 +117,7 @@ namespace hpx::components {
         /// \returns A future holding the list of global addresses which
         ///          represent the newly created objects
         ///
-        template <typename Component, typename... Ts>
+        template <bool WithCount, typename Component, typename... Ts>
         hpx::future<std::vector<bulk_locality_result>> bulk_create(
             std::size_t count, Ts&&... vs) const
         {
@@ -120,13 +126,20 @@ namespace hpx::components {
             if (!id_)
             {
                 id = naming::get_id_from_locality_id(agas::get_locality_id());
-                f = bulk_create_async<Component>(
+                f = bulk_create_async<WithCount, Component>(
+                    id, count, HPX_FORWARD(Ts, vs)...);
+            }
+            else if (!naming::detail::is_migratable(id_.get_gid()))
+            {
+                id = naming::get_id_from_locality_id(
+                    naming::get_locality_id_from_id(id_));
+                f = bulk_create_async<WithCount, Component>(
                     id, count, HPX_FORWARD(Ts, vs)...);
             }
             else
             {
                 id = id_;
-                f = bulk_create_colocated_async<Component>(
+                f = bulk_create_colocated_async<WithCount, Component>(
                     id, count, HPX_FORWARD(Ts, vs)...);
             }
 
@@ -160,6 +173,13 @@ namespace hpx::components {
                     naming::get_id_from_locality_id(agas::get_locality_id()),
                     HPX_FORWARD(Ts, vs)...);
             }
+            if (!naming::detail::is_migratable(id_.get_gid()))
+            {
+                return hpx::detail::async_impl<Action>(policy,
+                    naming::get_id_from_locality_id(
+                        naming::get_locality_id_from_id(id_)),
+                    HPX_FORWARD(Ts, vs)...);
+            }
             return hpx::detail::async_colocated<Action>(
                 id_, HPX_FORWARD(Ts, vs)...);
         }
@@ -177,6 +197,13 @@ namespace hpx::components {
                     naming::get_id_from_locality_id(agas::get_locality_id()),
                     HPX_FORWARD(Callback, cb), HPX_FORWARD(Ts, vs)...);
             }
+            if (!naming::detail::is_migratable(id_.get_gid()))
+            {
+                return hpx::detail::async_cb_impl<Action>(policy,
+                    naming::get_id_from_locality_id(
+                        naming::get_locality_id_from_id(id_)),
+                    HPX_FORWARD(Callback, cb), HPX_FORWARD(Ts, vs)...);
+            }
             return hpx::detail::async_colocated_cb<Action>(
                 id_, HPX_FORWARD(Callback, cb), HPX_FORWARD(Ts, vs)...);
         }
@@ -194,6 +221,14 @@ namespace hpx::components {
                     naming::get_id_from_locality_id(agas::get_locality_id()),
                     policy, HPX_FORWARD(Ts, vs)...);
             }
+            if (!naming::detail::is_migratable(id_.get_gid()))
+            {
+                return hpx::detail::post_impl<Action>(
+                    HPX_FORWARD(Continuation, c),
+                    naming::get_id_from_locality_id(
+                        naming::get_locality_id_from_id(id_)),
+                    policy, HPX_FORWARD(Ts, vs)...);
+            }
             return hpx::detail::post_colocated<Action>(
                 HPX_FORWARD(Continuation, c), id_, HPX_FORWARD(Ts, vs)...);
         }
@@ -207,6 +242,13 @@ namespace hpx::components {
                     naming::get_id_from_locality_id(agas::get_locality_id()),
                     policy, HPX_FORWARD(Ts, vs)...);
             }
+            if (!naming::detail::is_migratable(id_.get_gid()))
+            {
+                return hpx::detail::post_impl<Action>(
+                    naming::get_id_from_locality_id(
+                        naming::get_locality_id_from_id(id_)),
+                    policy, HPX_FORWARD(Ts, vs)...);
+            }
             return hpx::detail::post_colocated<Action>(
                 id_, HPX_FORWARD(Ts, vs)...);
         }
@@ -226,6 +268,14 @@ namespace hpx::components {
                     naming::get_id_from_locality_id(agas::get_locality_id()),
                     policy, HPX_FORWARD(Callback, cb), HPX_FORWARD(Ts, vs)...);
             }
+            if (!naming::detail::is_migratable(id_.get_gid()))
+            {
+                return hpx::detail::post_cb_impl<Action>(
+                    HPX_FORWARD(Continuation, c),
+                    naming::get_id_from_locality_id(
+                        naming::get_locality_id_from_id(id_)),
+                    policy, HPX_FORWARD(Callback, cb), HPX_FORWARD(Ts, vs)...);
+            }
             return hpx::detail::post_colocated_cb<Action>(
                 HPX_FORWARD(Continuation, c), id_, HPX_FORWARD(Callback, cb),
                 HPX_FORWARD(Ts, vs)...);
@@ -240,6 +290,13 @@ namespace hpx::components {
                     naming::get_id_from_locality_id(agas::get_locality_id()),
                     policy, HPX_FORWARD(Callback, cb), HPX_FORWARD(Ts, vs)...);
             }
+            if (!naming::detail::is_migratable(id_.get_gid()))
+            {
+                return hpx::detail::post_cb_impl<Action>(
+                    naming::get_id_from_locality_id(
+                        naming::get_locality_id_from_id(id_)),
+                    policy, HPX_FORWARD(Callback, cb), HPX_FORWARD(Ts, vs)...);
+            }
             return hpx::detail::post_colocated_cb<Action>(
                 id_, HPX_FORWARD(Callback, cb), HPX_FORWARD(Ts, vs)...);
         }
diff --git a/libs/full/distribution_policies/include/hpx/distribution_policies/container_distribution_policy.hpp b/libs/full/distribution_policies/include/hpx/distribution_policies/container_distribution_policy.hpp
index a0bde52afafa..2e2e3e118dc8 100644
--- a/libs/full/distribution_policies/include/hpx/distribution_policies/container_distribution_policy.hpp
+++ b/libs/full/distribution_policies/include/hpx/distribution_policies/container_distribution_policy.hpp
@@ -1,5 +1,5 @@
 //  Copyright (c) 2014 Bibek Ghimire
-//  Copyright (c) 2014-2023 Hartmut Kaiser
+//  Copyright (c) 2014-2024 Hartmut Kaiser
 //
 //  SPDX-License-Identifier: BSL-1.0
 //  Distributed under the Boost Software License, Version 1.0. (See accompanying
@@ -31,56 +31,59 @@ namespace hpx {
     struct container_distribution_policy
       : components::default_distribution_policy
     {
-    public:
-        constexpr container_distribution_policy() = default;
+        container_distribution_policy() = default;
 
-        container_distribution_policy operator()(
-            std::size_t num_partitions) const
+        container_distribution_policy operator()(std::size_t num_partitions,
+            traits::create_mode mode = traits::create_mode::resize) const
         {
-            return container_distribution_policy(
-                num_partitions, get_localities());
+            return {num_partitions, get_localities(), mode};
         }
 
-        container_distribution_policy operator()(
-            hpx::id_type const& locality) const
+        container_distribution_policy operator()(traits::create_mode mode) const
+        {
+            return container_distribution_policy(mode);
+        }
+
+        container_distribution_policy operator()(hpx::id_type const& locality,
+            traits::create_mode mode = traits::create_mode::resize) const
         {
-            return container_distribution_policy(locality);
+            return {locality, mode};
         }
 
         container_distribution_policy operator()(
-            std::vector<id_type> const& localities) const
+            std::vector<id_type> const& localities,
+            traits::create_mode mode = traits::create_mode::resize) const
         {
             if (num_partitions_ != static_cast<std::size_t>(-1))
             {
-                return container_distribution_policy(
-                    num_partitions_, localities);
+                return {num_partitions_, localities, mode};
             }
-            return container_distribution_policy(localities.size(), localities);
+            return {localities.size(), localities, mode};
         }
 
         container_distribution_policy operator()(
-            std::vector<id_type>&& localities) const
+            std::vector<id_type>&& localities,
+            traits::create_mode mode = traits::create_mode::resize) const
         {
             if (num_partitions_ != static_cast<std::size_t>(-1))
             {
-                return container_distribution_policy(
-                    num_partitions_, HPX_MOVE(localities));
+                return {num_partitions_, HPX_MOVE(localities), mode};
             }
-            return container_distribution_policy(
-                localities.size(), HPX_MOVE(localities));
+            return {localities.size(), HPX_MOVE(localities), mode};
         }
 
         container_distribution_policy operator()(std::size_t num_partitions,
-            std::vector<id_type> const& localities) const
+            std::vector<id_type> const& localities,
+            traits::create_mode mode = traits::create_mode::resize) const
         {
-            return container_distribution_policy(num_partitions, localities);
+            return {num_partitions, localities, mode};
         }
 
-        container_distribution_policy operator()(
-            std::size_t num_partitions, std::vector<id_type>&& localities) const
+        container_distribution_policy operator()(std::size_t num_partitions,
+            std::vector<id_type>&& localities,
+            traits::create_mode mode = traits::create_mode::resize) const
         {
-            return container_distribution_policy(
-                num_partitions, HPX_MOVE(localities));
+            return {num_partitions, HPX_MOVE(localities), mode};
         }
 
         ///////////////////////////////////////////////////////////////////////
@@ -110,6 +113,11 @@ namespace hpx {
             return *localities_;
         }
 
+        [[nodiscard]] constexpr traits::create_mode get_create_mode() const
+        {
+            return mode_;
+        }
+
     private:
         friend class hpx::serialization::access;
 
@@ -117,32 +125,41 @@ namespace hpx {
         void serialize(Archive& ar, const unsigned int /* version */)
         {
             // clang-format off
-            ar & localities_ & num_partitions_;
+            ar & localities_ & num_partitions_ & mode_;
             // clang-format on
         }
 
-        container_distribution_policy(
-            std::size_t num_partitions, std::vector<id_type> const& localities)
+        container_distribution_policy(std::size_t num_partitions,
+            std::vector<id_type> const& localities, traits::create_mode mode)
           : components::default_distribution_policy(localities)
           , num_partitions_(num_partitions)
+          , mode_(mode)
         {
         }
 
-        container_distribution_policy(
-            std::size_t num_partitions, std::vector<id_type>&& localities)
+        container_distribution_policy(std::size_t num_partitions,
+            std::vector<id_type>&& localities, traits::create_mode mode)
           : components::default_distribution_policy(HPX_MOVE(localities))
           , num_partitions_(num_partitions)
+          , mode_(mode)
         {
         }
 
-        explicit container_distribution_policy(hpx::id_type const& locality)
+        container_distribution_policy(
+            hpx::id_type const& locality, traits::create_mode mode)
           : components::default_distribution_policy(locality)
+          , mode_(mode)
+        {
+        }
+
+        explicit container_distribution_policy(traits::create_mode mode)
+          : mode_(mode)
         {
         }
 
-    private:
         // number of chunks to create
         std::size_t num_partitions_ = static_cast<std::size_t>(-1);
+        traits::create_mode mode_ = traits::create_mode::resize;
     };
 
     static container_distribution_policy const container_layout{};
@@ -164,5 +181,14 @@ namespace hpx {
                 return policy.get_num_partitions();
             }
         };
+
+        template <>
+        struct allocation_mode<container_distribution_policy>
+        {
+            static create_mode call(container_distribution_policy const& policy)
+            {
+                return policy.get_create_mode();
+            }
+        };
     }    // namespace traits
 }    // namespace hpx
diff --git a/libs/full/distribution_policies/include/hpx/distribution_policies/default_distribution_policy.hpp b/libs/full/distribution_policies/include/hpx/distribution_policies/default_distribution_policy.hpp
index 3edf6ca738ed..1de3c0f8e8cf 100644
--- a/libs/full/distribution_policies/include/hpx/distribution_policies/default_distribution_policy.hpp
+++ b/libs/full/distribution_policies/include/hpx/distribution_policies/default_distribution_policy.hpp
@@ -62,19 +62,7 @@ namespace hpx::components {
         ///
         /// \param locs     [in] The list of localities the new instance should
         ///                 represent
-        default_distribution_policy operator()(
-            std::vector<id_type> const& locs) const
-        {
-            return default_distribution_policy(locs);
-        }
-
-        /// Create a new \a default_distribution policy representing the given
-        /// set of localities.
-        ///
-        /// \param locs     [in] The list of localities the new instance should
-        ///                 represent
-        default_distribution_policy operator()(
-            std::vector<id_type>&& locs) const
+        default_distribution_policy operator()(std::vector<id_type> locs) const
         {
             return default_distribution_policy(HPX_MOVE(locs));
         }
@@ -84,9 +72,9 @@ namespace hpx::components {
         ///
         /// \param loc     [in] The locality the new instance should
         ///                 represent
-        default_distribution_policy operator()(id_type const& loc) const
+        default_distribution_policy operator()(id_type loc) const
         {
-            return default_distribution_policy(loc);
+            return default_distribution_policy(HPX_MOVE(loc));
         }
 
         /// Create one object on one of the localities associated by
@@ -140,7 +128,7 @@ namespace hpx::components {
         /// \returns A future holding the list of global addresses that
         ///          represent the newly created objects
         ///
-        template <typename Component, typename... Ts>
+        template <bool WithCount, typename Component, typename... Ts>
         hpx::future<std::vector<bulk_locality_result>> bulk_create(
             std::size_t count, Ts&&... vs) const
         {
@@ -151,7 +139,7 @@ namespace hpx::components {
                 objs.reserve(localities_->size());
                 for (hpx::id_type const& loc : *localities_)
                 {
-                    objs.emplace_back(bulk_create_async<Component>(
+                    objs.emplace_back(bulk_create_async<WithCount, Component>(
                         loc, get_num_items(count, loc), vs...));
                 }
 
@@ -180,7 +168,8 @@ namespace hpx::components {
             hpx::id_type id = get_next_target();
 
             hpx::future<std::vector<hpx::id_type>> f =
-                bulk_create_async<Component>(id, count, HPX_FORWARD(Ts, vs)...);
+                bulk_create_async<WithCount, Component>(
+                    id, count, HPX_FORWARD(Ts, vs)...);
 
             return f.then(hpx::launch::sync,
                 [id = HPX_MOVE(id)](hpx::future<std::vector<hpx::id_type>>&& f)
@@ -317,9 +306,9 @@ namespace hpx::components {
 
     protected:
         /// \cond NOINTERNAL
-        explicit default_distribution_policy(
-            std::vector<id_type> const& localities)
-          : localities_(std::make_shared<std::vector<id_type>>(localities))
+        explicit default_distribution_policy(std::vector<id_type> localities)
+          : localities_(
+                std::make_shared<std::vector<id_type>>(HPX_MOVE(localities)))
         {
             if (localities_->empty())
             {
@@ -330,20 +319,9 @@ namespace hpx::components {
             }
         }
 
-        explicit default_distribution_policy(std::vector<id_type>&& localities)
+        explicit default_distribution_policy(id_type locality)
           : localities_(
-                std::make_shared<std::vector<id_type>>(HPX_MOVE(localities)))
-        {
-            if (localities_->empty())
-            {
-                HPX_THROW_EXCEPTION(hpx::error::invalid_status,
-                    "default_distribution_policy::default_distribution_policy",
-                    "unexpectedly empty list of localities");
-            }
-        }
-
-        explicit default_distribution_policy(id_type const& locality)
-          : localities_(std::make_shared<std::vector<id_type>>(1, locality))
+                std::make_shared<std::vector<id_type>>(1, HPX_MOVE(locality)))
         {
         }
 
diff --git a/libs/full/distribution_policies/include/hpx/distribution_policies/explicit_container_distribution_policy.hpp b/libs/full/distribution_policies/include/hpx/distribution_policies/explicit_container_distribution_policy.hpp
new file mode 100644
index 000000000000..23a89ba9ed72
--- /dev/null
+++ b/libs/full/distribution_policies/include/hpx/distribution_policies/explicit_container_distribution_policy.hpp
@@ -0,0 +1,160 @@
+//  Copyright (c) 2014-2024 Hartmut Kaiser
+//
+//  SPDX-License-Identifier: BSL-1.0
+//  Distributed under the Boost Software License, Version 1.0. (See accompanying
+//  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#pragma once
+
+#include <hpx/config.hpp>
+#include <hpx/actions_base/traits/is_distribution_policy.hpp>
+#include <hpx/assert.hpp>
+#include <hpx/components_base/agas_interface.hpp>
+#include <hpx/distribution_policies/default_distribution_policy.hpp>
+#include <hpx/serialization/serialize.hpp>
+#include <hpx/serialization/shared_ptr.hpp>
+#include <hpx/serialization/vector.hpp>
+
+#include <algorithm>
+#include <cstddef>
+#include <memory>
+#include <type_traits>
+#include <utility>
+#include <vector>
+
+namespace hpx {
+
+    ///////////////////////////////////////////////////////////////////////////
+    // This class specifies the block chunking policy parameters to use for the
+    // partitioning of the data in a hpx::partitioned_vector
+    struct explicit_container_distribution_policy
+      : components::default_distribution_policy
+    {
+        explicit_container_distribution_policy() = default;
+
+        explicit_container_distribution_policy operator()(
+            std::vector<std::size_t> sizes,
+            traits::create_mode mode = traits::create_mode::resize) const
+        {
+            return {HPX_MOVE(sizes), get_localities(), mode};
+        }
+
+        explicit_container_distribution_policy operator()(
+            std::vector<std::size_t> sizes, hpx::id_type locality,
+            traits::create_mode mode = traits::create_mode::resize) const
+        {
+            return {HPX_MOVE(sizes), HPX_MOVE(locality), mode};
+        }
+
+        explicit_container_distribution_policy operator()(
+            std::vector<std::size_t> sizes, std::vector<id_type> localities,
+            traits::create_mode mode = traits::create_mode::resize) const
+        {
+            return {HPX_MOVE(sizes), HPX_MOVE(localities), mode};
+        }
+
+        ///////////////////////////////////////////////////////////////////////
+        [[nodiscard]] std::size_t get_num_partitions() const noexcept
+        {
+            return sizes_.size();
+        }
+
+        [[nodiscard]] std::vector<hpx::id_type> get_localities() const
+        {
+            if (!localities_)
+            {
+                // use this locality, if this object was default constructed
+                return std::vector<id_type>(1,
+                    naming::get_id_from_locality_id(agas::get_locality_id()));
+            }
+
+            HPX_ASSERT(!localities_->empty());
+            return *localities_;
+        }
+
+        [[nodiscard]] std::vector<std::size_t> get_sizes() const
+        {
+            return sizes_;
+        }
+
+        [[nodiscard]] constexpr traits::create_mode get_create_mode() const
+        {
+            return mode_;
+        }
+
+    private:
+        friend class hpx::serialization::access;
+
+        template <typename Archive>
+        void serialize(Archive& ar, unsigned int const /* version */)
+        {
+            // clang-format off
+            ar & localities_ & sizes_ & mode_;
+            // clang-format on
+        }
+
+        explicit_container_distribution_policy(std::vector<std::size_t> sizes,
+            std::vector<id_type> localities, traits::create_mode mode)
+          : components::default_distribution_policy(HPX_MOVE(localities))
+          , sizes_(HPX_MOVE(sizes))
+          , mode_(mode)
+        {
+        }
+
+        explicit_container_distribution_policy(std::vector<std::size_t> sizes,
+            hpx::id_type locality, traits::create_mode mode)
+          : components::default_distribution_policy(HPX_MOVE(locality))
+          , sizes_(HPX_MOVE(sizes))
+          , mode_(mode)
+        {
+        }
+
+        // number of chunks to create
+        std::vector<std::size_t> sizes_;
+        traits::create_mode mode_ = traits::create_mode::resize;
+    };
+
+    static explicit_container_distribution_policy const
+        explicit_container_layout{};
+
+    ///////////////////////////////////////////////////////////////////////////
+    namespace traits {
+
+        template <>
+        struct is_distribution_policy<explicit_container_distribution_policy>
+          : std::true_type
+        {
+        };
+
+        template <>
+        struct num_container_partitions<explicit_container_distribution_policy>
+        {
+            static std::size_t call(
+                explicit_container_distribution_policy const& policy)
+            {
+                return policy.get_num_partitions();
+            }
+        };
+
+        template <>
+        struct container_partition_sizes<explicit_container_distribution_policy>
+        {
+            static std::vector<std::size_t> call(
+                explicit_container_distribution_policy const& policy,
+                std::size_t)
+            {
+                return policy.get_sizes();
+            }
+        };
+
+        template <>
+        struct allocation_mode<explicit_container_distribution_policy>
+        {
+            static create_mode call(
+                explicit_container_distribution_policy const& policy)
+            {
+                return policy.get_create_mode();
+            }
+        };
+    }    // namespace traits
+}    // namespace hpx
diff --git a/libs/full/distribution_policies/include/hpx/distribution_policies/target_distribution_policy.hpp b/libs/full/distribution_policies/include/hpx/distribution_policies/target_distribution_policy.hpp
index 42f2ee95a900..6a889f5eb37c 100644
--- a/libs/full/distribution_policies/include/hpx/distribution_policies/target_distribution_policy.hpp
+++ b/libs/full/distribution_policies/include/hpx/distribution_policies/target_distribution_policy.hpp
@@ -90,7 +90,7 @@ namespace hpx::components {
         /// \returns A future holding the list of global addresses which
         ///          represent the newly created objects
         ///
-        template <typename Component, typename... Ts>
+        template <bool WithCount, typename Component, typename... Ts>
         hpx::future<std::vector<bulk_locality_result>> bulk_create(
             std::size_t count, Ts&&... vs) const
         {
@@ -98,7 +98,7 @@ namespace hpx::components {
             // locality
             hpx::id_type id = get_next_target();
             hpx::future<std::vector<hpx::id_type>> f =
-                components::bulk_create_async<Component>(
+                components::bulk_create_async<WithCount, Component>(
                     id, count, HPX_FORWARD(Ts, vs)...);
 
             return f.then(hpx::launch::sync,
diff --git a/libs/full/naming/src/credit_handling.cpp b/libs/full/naming/src/credit_handling.cpp
index 175d10eb83c2..97d684f73f49 100644
--- a/libs/full/naming/src/credit_handling.cpp
+++ b/libs/full/naming/src/credit_handling.cpp
@@ -615,6 +615,9 @@ namespace hpx::naming {
                     "client instead");
             }
 
+            using preprocess_gid_types =
+                serialization::detail::preprocess_gid_types;
+
             gid_type new_gid;
             if (hpx::id_type::management_type::unmanaged == type)
             {
@@ -628,16 +631,15 @@ namespace hpx::naming {
             }
             else
             {
-                auto& split_gids = ar.get_extra_data<
-                    serialization::detail::preprocess_gid_types>();
+                auto& split_gids = ar.get_extra_data<preprocess_gid_types>();
 
                 new_gid = split_gids.get_new_gid(id_impl);
                 HPX_ASSERT(new_gid != invalid_gid);
             }
 
 #if defined(HPX_DEBUG)
-            auto const* split_gids = ar.try_get_extra_data<
-                serialization::detail::preprocess_gid_types>();
+            auto const* split_gids =
+                ar.try_get_extra_data<preprocess_gid_types>();
             HPX_ASSERT(!split_gids || !split_gids->has_gid(id_impl));
 #endif
 
diff --git a/libs/full/runtime_components/include/hpx/runtime_components/create_component_helpers.hpp b/libs/full/runtime_components/include/hpx/runtime_components/create_component_helpers.hpp
index dfc46a5fcc62..dda2afad561b 100644
--- a/libs/full/runtime_components/include/hpx/runtime_components/create_component_helpers.hpp
+++ b/libs/full/runtime_components/include/hpx/runtime_components/create_component_helpers.hpp
@@ -27,7 +27,7 @@ namespace hpx::components {
         template <typename Component, typename... Ts>
         struct create_component_action;
 
-        template <typename Component, typename... Ts>
+        template <bool WithCount, typename Component, typename... Ts>
         struct bulk_create_component_action;
     }    // namespace server
 
@@ -50,7 +50,7 @@ namespace hpx::components {
         return hpx::async<action_type>(gid, HPX_FORWARD(Ts, vs)...);
     }
 
-    template <typename Component, typename... Ts>
+    template <bool WithCount, typename Component, typename... Ts>
     future<std::vector<hpx::id_type>> bulk_create_async(
         hpx::id_type const& gid, std::size_t count, Ts&&... vs)
     {
@@ -62,8 +62,8 @@ namespace hpx::components {
                 "a locality");
         }
 
-        using action_type = server::bulk_create_component_action<Component,
-            std::decay_t<Ts>...>;
+        using action_type = server::bulk_create_component_action<WithCount,
+            Component, std::decay_t<Ts>...>;
 
         return hpx::async<action_type>(gid, count, HPX_FORWARD(Ts, vs)...);
     }
@@ -74,11 +74,12 @@ namespace hpx::components {
         return create_async<Component>(gid, HPX_FORWARD(Ts, vs)...).get();
     }
 
-    template <typename Component, typename... Ts>
+    template <bool WithCount, typename Component, typename... Ts>
     std::vector<hpx::id_type> bulk_create(
         hpx::id_type const& gid, std::size_t count, Ts&&... vs)
     {
-        return bulk_create_async<Component>(gid, count, HPX_FORWARD(Ts, vs)...)
+        return bulk_create_async<WithCount, Component>(
+            gid, count, HPX_FORWARD(Ts, vs)...)
             .get();
     }
 
@@ -99,22 +100,22 @@ namespace hpx::components {
         return create_colocated_async(gid, HPX_FORWARD(Ts, vs)...).get();
     }
 
-    template <typename Component, typename... Ts>
+    template <bool WithCount, typename Component, typename... Ts>
     static future<std::vector<hpx::id_type>> bulk_create_colocated_async(
         hpx::id_type const& gid, std::size_t count, Ts&&... vs)
     {
-        using action_type = server::bulk_create_component_action<Component,
-            std::decay_t<Ts>...>;
+        using action_type = server::bulk_create_component_action<WithCount,
+            Component, std::decay_t<Ts>...>;
 
         return hpx::detail::async_colocated<action_type>(
             gid, count, HPX_FORWARD(Ts, vs)...);
     }
 
-    template <typename Component, typename... Ts>
+    template <bool WithCount, typename Component, typename... Ts>
     std::vector<hpx::id_type> bulk_create_colocated(
         hpx::id_type const& id, std::size_t count, Ts&&... vs)
     {
-        return bulk_create_colocated_async<Component>(
+        return bulk_create_colocated_async<WithCount, Component>(
             id, count, HPX_FORWARD(Ts, vs)...)
             .get();
     }
diff --git a/libs/full/runtime_components/include/hpx/runtime_components/new.hpp b/libs/full/runtime_components/include/hpx/runtime_components/new.hpp
index 41c2b6e1ceeb..21f0df716873 100644
--- a/libs/full/runtime_components/include/hpx/runtime_components/new.hpp
+++ b/libs/full/runtime_components/include/hpx/runtime_components/new.hpp
@@ -282,7 +282,7 @@ namespace hpx::components {
             static type call(
                 hpx::id_type const& locality, std::size_t count, Ts&&... vs)
             {
-                return components::bulk_create_async<Component>(
+                return components::bulk_create_async<false, Component>(
                     locality, count, HPX_FORWARD(Ts, vs)...);
             }
 
@@ -294,7 +294,7 @@ namespace hpx::components {
                     typename DistPolicy::bulk_locality_result;
 
                 hpx::future<std::vector<bulk_locality_result>> f =
-                    policy.template bulk_create<Component>(
+                    policy.template bulk_create<false, Component>(
                         count, HPX_FORWARD(Ts, vs)...);
 
                 return f.then(launch::sync,
diff --git a/libs/full/runtime_distributed/include/hpx/runtime_distributed/runtime_support.hpp b/libs/full/runtime_distributed/include/hpx/runtime_distributed/runtime_support.hpp
index a6e2a0de257d..4b0a4be19a52 100644
--- a/libs/full/runtime_distributed/include/hpx/runtime_distributed/runtime_support.hpp
+++ b/libs/full/runtime_distributed/include/hpx/runtime_distributed/runtime_support.hpp
@@ -1,4 +1,4 @@
-//  Copyright (c) 2007-2013 Hartmut Kaiser
+//  Copyright (c) 2007-2024 Hartmut Kaiser
 //
 //  SPDX-License-Identifier: BSL-1.0
 //  Distributed under the Boost Software License, Version 1.0. (See accompanying
@@ -58,81 +58,81 @@ namespace hpx { namespace components {
 
         /// Asynchronously create N new default constructed components using
         /// the runtime_support
-        template <typename Component, typename... Ts>
+        template <bool WithCount, typename Component, typename... Ts>
         std::vector<hpx::id_type> bulk_create_component(
             std::size_t /* count */, Ts&&... vs)
         {
-            return this->base_type::template bulk_create_component<Component>(
-                gid_, HPX_FORWARD(Ts, vs)...);
+            return this->base_type::template bulk_create_component<WithCount,
+                Component>(gid_, HPX_FORWARD(Ts, vs)...);
         }
 
         /// Asynchronously create a new component using the runtime_support
-        template <typename Component, typename... Ts>
+        template <bool WithCount, typename Component, typename... Ts>
         hpx::future<std::vector<hpx::id_type>> bulk_create_components_async(
             std::size_t /* count */, Ts&&... vs)
         {
-            return this->base_type::template bulk_create_component<Component>(
-                gid_, HPX_FORWARD(Ts, vs)...);
+            return this->base_type::template bulk_create_component<WithCount,
+                Component>(gid_, HPX_FORWARD(Ts, vs)...);
         }
 
         ///////////////////////////////////////////////////////////////////////
-        hpx::future<int> load_components_async()
+        hpx::future<int> load_components_async() const
         {
             return this->base_type::load_components_async(gid_);
         }
 
-        int load_components()
+        int load_components() const
         {
             return this->base_type::load_components(gid_);
         }
 
-        hpx::future<void> call_startup_functions_async(bool pre_startup)
+        hpx::future<void> call_startup_functions_async(bool pre_startup) const
         {
             return this->base_type::call_startup_functions_async(
                 gid_, pre_startup);
         }
 
-        void call_startup_functions(bool pre_startup)
+        void call_startup_functions(bool pre_startup) const
         {
             this->base_type::call_startup_functions(gid_, pre_startup);
         }
 
         /// \brief Shutdown the given runtime system
-        hpx::future<void> shutdown_async(double timeout = -1)
+        hpx::future<void> shutdown_async(double timeout = -1) const
         {
             return this->base_type::shutdown_async(gid_, timeout);
         }
 
-        void shutdown(double timeout = -1)
+        void shutdown(double timeout = -1) const
         {
             this->base_type::shutdown(gid_, timeout);
         }
 
         /// \brief Shutdown the runtime systems of all localities
-        void shutdown_all(double timeout = -1)
+        void shutdown_all(double timeout = -1) const
         {
             this->base_type::shutdown_all(gid_, timeout);
         }
 
         /// \brief Terminate the given runtime system
-        hpx::future<void> terminate_async()
+        hpx::future<void> terminate_async() const
         {
             return this->base_type::terminate_async(gid_);
         }
 
-        void terminate()
+        void terminate() const
         {
             this->base_type::terminate(gid_);
         }
 
         /// \brief Terminate the runtime systems of all localities
-        void terminate_all()
+        void terminate_all() const
         {
             this->base_type::terminate_all(gid_);
         }
 
         /// \brief Retrieve configuration information
-        void get_config(util::section& ini)
+        void get_config(util::section& ini) const
         {
             this->base_type::get_config(gid_, ini);
         }
diff --git a/libs/full/runtime_distributed/include/hpx/runtime_distributed/server/runtime_support.hpp b/libs/full/runtime_distributed/include/hpx/runtime_distributed/server/runtime_support.hpp
index c4770a6944f4..09196655947a 100644
--- a/libs/full/runtime_distributed/include/hpx/runtime_distributed/server/runtime_support.hpp
+++ b/libs/full/runtime_distributed/include/hpx/runtime_distributed/server/runtime_support.hpp
@@ -125,10 +125,11 @@ namespace hpx::components::server {
         template <typename Component, typename T, typename... Ts>
         naming::gid_type create_component(T v, Ts... vs);
 
-        template <typename Component>
+        template <bool WithCount, typename Component>
         std::vector<naming::gid_type> bulk_create_component(std::size_t count);
 
-        template <typename Component, typename T, typename... Ts>
+        template <bool WithCount, typename Component, typename T,
+            typename... Ts>
         std::vector<naming::gid_type> bulk_create_component(
             std::size_t count, T v, Ts... vs);
 
@@ -418,7 +419,7 @@ namespace hpx::components::server {
     }
 #endif
 
-    template <typename Component>
+    template <bool WithCount, typename Component>
     std::vector<naming::gid_type> runtime_support::bulk_create_component(
         std::size_t count)
     {
@@ -431,7 +432,14 @@ namespace hpx::components::server {
         typedef typename Component::wrapping_type wrapping_type;
         for (std::size_t i = 0; i != count; ++i)
         {
-            ids.emplace_back(create<wrapping_type>());
+            if constexpr (WithCount)
+            {
+                ids.emplace_back(create<wrapping_type>(i));
+            }
+            else
+            {
+                ids.emplace_back(create<wrapping_type>());
+            }
         }
 
         LRT_(info).format("successfully created {} component(s) of type: {}",
@@ -440,7 +448,7 @@ namespace hpx::components::server {
         return ids;
     }
 
-    template <typename Component, typename T, typename... Ts>
+    template <bool WithCount, typename Component, typename T, typename... Ts>
     std::vector<naming::gid_type> runtime_support::bulk_create_component(
         std::size_t count, T v, Ts... vs)
     {
@@ -453,7 +461,14 @@ namespace hpx::components::server {
         typedef typename Component::wrapping_type wrapping_type;
         for (std::size_t i = 0; i != count; ++i)
         {
-            ids.push_back(create<wrapping_type>(v, vs...));
+            if constexpr (WithCount)
+            {
+                ids.push_back(create<wrapping_type>(i, v, vs...));
+            }
+            else
+            {
+                ids.push_back(create<wrapping_type>(v, vs...));
+            }
         }
 
         LRT_(info).format("successfully created {} component(s) of type: {}",
@@ -634,40 +649,42 @@ namespace hpx::components::server {
     };
 
     ///////////////////////////////////////////////////////////////////////////
-    template <typename Component, typename... Ts>
+    template <bool WithCount, typename Component, typename... Ts>
     struct bulk_create_component_action
       : ::hpx::actions::action<std::vector<naming::gid_type> (
                                    runtime_support::*)(std::size_t, Ts...),
-            &runtime_support::bulk_create_component<Component, Ts...>,
-            bulk_create_component_action<Component, Ts...>>
+            &runtime_support::bulk_create_component<WithCount, Component,
+                Ts...>,
+            bulk_create_component_action<WithCount, Component, Ts...>>
     {
     };
 
-    template <typename Component>
-    struct bulk_create_component_action<Component>
+    template <bool WithCount, typename Component>
+    struct bulk_create_component_action<WithCount, Component>
       : ::hpx::actions::action<std::vector<naming::gid_type> (
                                    runtime_support::*)(std::size_t),
-            &runtime_support::bulk_create_component<Component>,
-            bulk_create_component_action<Component>>
+            &runtime_support::bulk_create_component<WithCount, Component>,
+            bulk_create_component_action<WithCount, Component>>
     {
     };
 
-    template <typename Component, typename... Ts>
+    template <bool WithCount, typename Component, typename... Ts>
     struct bulk_create_component_direct_action
       : ::hpx::actions::direct_action<std::vector<naming::gid_type> (
                                           runtime_support::*)(
                                           std::size_t, Ts...),
-            &runtime_support::bulk_create_component<Component, Ts...>,
-            bulk_create_component_direct_action<Component, Ts...>>
+            &runtime_support::bulk_create_component<WithCount, Component,
+                Ts...>,
+            bulk_create_component_direct_action<WithCount, Component, Ts...>>
     {
     };
 
-    template <typename Component>
-    struct bulk_create_component_direct_action<Component>
+    template <bool WithCount, typename Component>
+    struct bulk_create_component_direct_action<WithCount, Component>
       : ::hpx::actions::direct_action<std::vector<naming::gid_type> (
                                           runtime_support::*)(std::size_t),
-            &runtime_support::bulk_create_component<Component>,
-            bulk_create_component_direct_action<Component>>
+            &runtime_support::bulk_create_component<WithCount, Component>,
+            bulk_create_component_direct_action<WithCount, Component>>
     {
     };
 
diff --git a/libs/full/runtime_distributed/include/hpx/runtime_distributed/stubs/runtime_support.hpp b/libs/full/runtime_distributed/include/hpx/runtime_distributed/stubs/runtime_support.hpp
index 673d7c864812..479eb66a5391 100644
--- a/libs/full/runtime_distributed/include/hpx/runtime_distributed/stubs/runtime_support.hpp
+++ b/libs/full/runtime_distributed/include/hpx/runtime_distributed/stubs/runtime_support.hpp
@@ -1,4 +1,4 @@
-//  Copyright (c) 2007-2021 Hartmut Kaiser
+//  Copyright (c) 2007-2024 Hartmut Kaiser
 //  Copyright (c)      2011 Bryce Lelbach
 //
 //  SPDX-License-Identifier: BSL-1.0
@@ -68,14 +68,14 @@ namespace hpx { namespace components { namespace stubs {
         }
 
         /// Create multiple new components \a type using the runtime_support
-        /// colocated with the with the given \a targetgid. This is a
+        /// colocated with the given \a targetgid. This is a
         /// non-blocking call.
-        template <typename Component, typename... Ts>
+        template <bool WithCount, typename Component, typename... Ts>
         static hpx::future<std::vector<hpx::id_type>>
         bulk_create_component_colocated_async(
             hpx::id_type const& gid, std::size_t count, Ts&&... vs)
         {
-            typedef server::bulk_create_component_action<Component,
+            typedef server::bulk_create_component_action<WithCount, Component,
                 typename std::decay<Ts>::type...>
                 action_type;
 
@@ -84,20 +84,20 @@ namespace hpx { namespace components { namespace stubs {
         }
 
         /// Create multiple new components \a type using the runtime_support
-        /// colocated with the with the given \a targetgid. Block for the
+        /// colocated with the given \a targetgid. Block for the
         /// creation to finish.
-        template <typename Component, typename... Ts>
+        template <bool WithCount, typename Component, typename... Ts>
         static std::vector<hpx::id_type> bulk_create_component_colocated(
             hpx::id_type const& gid, std::size_t count, Ts&&... vs)
         {
-            return bulk_create_component_colocated_async<Component>(
+            return bulk_create_component_colocated_async<WithCount, Component>(
                 gid, count, HPX_FORWARD(Ts, vs)...)
                 .get();
         }
 
         /// Create multiple new components \a type using the runtime_support
         /// on the given locality. This is a  non-blocking call.
-        template <typename Component, typename... Ts>
+        template <bool WithCount, typename Component, typename... Ts>
         static hpx::future<std::vector<hpx::id_type>>
         bulk_create_component_async(
             hpx::id_type const& gid, std::size_t count, Ts&&... vs)
@@ -111,7 +111,7 @@ namespace hpx { namespace components { namespace stubs {
                 return hpx::make_ready_future(std::vector<hpx::id_type>());
             }
 
-            typedef server::bulk_create_component_action<Component,
+            typedef server::bulk_create_component_action<WithCount, Component,
                 typename std::decay<Ts>::type...>
                 action_type;
             return hpx::async<action_type>(gid, count, HPX_FORWARD(Ts, vs)...);
diff --git a/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/all_any_none.hpp b/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/all_any_none.hpp
index 09d52e4aabe8..407f0cbeb311 100644
--- a/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/all_any_none.hpp
+++ b/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/all_any_none.hpp
@@ -25,7 +25,8 @@
 #include <utility>
 #include <vector>
 
-namespace hpx { namespace parallel {
+namespace hpx::parallel {
+
     ///////////////////////////////////////////////////////////////////////////
     // segmented_all_any_none
     namespace detail {
@@ -479,10 +480,10 @@ namespace hpx { namespace parallel {
         }
         /// \endcond
     }    // namespace detail
-}}    // namespace hpx::parallel
+}    // namespace hpx::parallel
 
 // The segmented iterators we support all live in namespace hpx::segmented
-namespace hpx { namespace segmented {
+namespace hpx::segmented {
 
     // clang-format off
     template <typename InIter,
@@ -603,4 +604,4 @@ namespace hpx { namespace segmented {
             hpx::parallel::detail::all_of(), HPX_FORWARD(ExPolicy, policy),
             first, last, HPX_FORWARD(F, f), hpx::identity_v, is_seq());
     }
-}}    // namespace hpx::segmented
+}    // namespace hpx::segmented
diff --git a/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/for_each.hpp b/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/for_each.hpp
index 9b009de6d56e..8e8c27cefb28 100644
--- a/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/for_each.hpp
+++ b/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/for_each.hpp
@@ -25,25 +25,26 @@
 #include <utility>
 #include <vector>
 
-namespace hpx { namespace parallel {
+namespace hpx::parallel {
 
     ///////////////////////////////////////////////////////////////////////////
     // segmented_for_each
     namespace detail {
+
         ///////////////////////////////////////////////////////////////////////
         /// \cond NOINTERNAL
 
         // sequential remote implementation
         template <typename Algo, typename ExPolicy, typename SegIter,
             typename F, typename Proj>
-        static typename util::detail::algorithm_result<ExPolicy, SegIter>::type
+        static util::detail::algorithm_result_t<ExPolicy, SegIter>
         segmented_for_each(Algo&& algo, ExPolicy const& policy, SegIter first,
             SegIter last, F&& f, Proj&& proj, std::true_type)
         {
-            typedef hpx::traits::segmented_iterator_traits<SegIter> traits;
-            typedef typename traits::segment_iterator segment_iterator;
-            typedef typename traits::local_iterator local_iterator_type;
-            typedef util::detail::algorithm_result<ExPolicy, SegIter> result;
+            using traits = hpx::traits::segmented_iterator_traits<SegIter>;
+            using segment_iterator = typename traits::segment_iterator;
+            using local_iterator_type = typename traits::local_iterator;
+            using result = util::detail::algorithm_result<ExPolicy, SegIter>;
 
             segment_iterator sit = traits::segment(first);
             segment_iterator send = traits::segment(last);
@@ -73,7 +74,7 @@ namespace hpx { namespace parallel {
                         std::true_type(), beg, end, f, proj);
                 }
 
-                // handle all of the full partitions
+                // handle all full partitions
                 for (++sit; sit != send; ++sit)
                 {
                     beg = traits::begin(sit);
@@ -105,18 +106,17 @@ namespace hpx { namespace parallel {
         // parallel remote implementation
         template <typename Algo, typename ExPolicy, typename SegIter,
             typename F, typename Proj>
-        static typename util::detail::algorithm_result<ExPolicy, SegIter>::type
+        static util::detail::algorithm_result_t<ExPolicy, SegIter>
         segmented_for_each(Algo&& algo, ExPolicy const& policy, SegIter first,
             SegIter last, F&& f, Proj&& proj, std::false_type)
         {
-            typedef hpx::traits::segmented_iterator_traits<SegIter> traits;
-            typedef typename traits::segment_iterator segment_iterator;
-            typedef typename traits::local_iterator local_iterator_type;
-            typedef util::detail::algorithm_result<ExPolicy, SegIter> result;
+            using traits = hpx::traits::segmented_iterator_traits<SegIter>;
+            using segment_iterator = typename traits::segment_iterator;
+            using local_iterator_type = typename traits::local_iterator;
+            using result = util::detail::algorithm_result<ExPolicy, SegIter>;
 
-            typedef std::integral_constant<bool,
-                !hpx::traits::is_forward_iterator<SegIter>::value>
-                forced_seq;
+            using forced_seq = std::integral_constant<bool,
+                !hpx::traits::is_forward_iterator_v<SegIter>>;
 
             segment_iterator sit = traits::segment(first);
             segment_iterator send = traits::segment(last);
@@ -146,7 +146,7 @@ namespace hpx { namespace parallel {
                         policy, forced_seq(), beg, end, f, proj));
                 }
 
-                // handle all of the full partitions
+                // handle all full partitions
                 for (++sit; sit != send; ++sit)
                 {
                     beg = traits::begin(sit);
@@ -181,22 +181,22 @@ namespace hpx { namespace parallel {
         }
         /// \endcond
     }    // namespace detail
-}}       // namespace hpx::parallel
+}    // namespace hpx::parallel
 
 // The segmented iterators we support all live in namespace hpx::segmented
-namespace hpx { namespace segmented {
+namespace hpx::segmented {
 
     // clang-format off
     template <typename InIter,
         typename F,
         HPX_CONCEPT_REQUIRES_(
-            hpx::traits::is_iterator<InIter>::value &&
-            hpx::traits::is_segmented_iterator<InIter>::value
+            hpx::traits::is_iterator_v<InIter> &&
+            hpx::traits::is_segmented_iterator_v<InIter>
         )>
     // clang-format on
     InIter tag_invoke(hpx::for_each_t, InIter first, InIter last, F&& f)
     {
-        static_assert((hpx::traits::is_forward_iterator<InIter>::value),
+        static_assert((hpx::traits::is_forward_iterator_v<InIter>),
             "Requires at least input iterator.");
 
         using iterator_traits = hpx::traits::segmented_iterator_traits<InIter>;
@@ -222,12 +222,11 @@ namespace hpx { namespace segmented {
             hpx::traits::is_segmented_iterator_v<SegIter>
         )>
     // clang-format on
-    typename hpx::parallel::util::detail::algorithm_result<ExPolicy,
-        SegIter>::type
+    hpx::parallel::util::detail::algorithm_result_t<ExPolicy, SegIter>
     tag_invoke(
         hpx::for_each_t, ExPolicy&& policy, SegIter first, SegIter last, F&& f)
     {
-        static_assert((hpx::traits::is_forward_iterator<SegIter>::value),
+        static_assert((hpx::traits::is_forward_iterator_v<SegIter>),
             "Requires at least forward iterator.");
 
         using is_seq = hpx::is_sequenced_execution_policy<ExPolicy>;
@@ -253,13 +252,13 @@ namespace hpx { namespace segmented {
     template <typename InIter, typename Size,
         typename F,
         HPX_CONCEPT_REQUIRES_(
-            hpx::traits::is_iterator<InIter>::value &&
-            hpx::traits::is_segmented_iterator<InIter>::value
+            hpx::traits::is_iterator_v<InIter> &&
+            hpx::traits::is_segmented_iterator_v<InIter>
         )>
     // clang-format on
     InIter tag_invoke(hpx::for_each_n_t, InIter first, Size count, F&& f)
     {
-        static_assert((hpx::traits::is_input_iterator<InIter>::value),
+        static_assert((hpx::traits::is_input_iterator_v<InIter>),
             "Requires at least input iterator.");
 
         using iterator_traits = hpx::traits::segmented_iterator_traits<InIter>;
@@ -270,7 +269,7 @@ namespace hpx { namespace segmented {
         }
 
         auto last = first;
-        hpx::parallel::detail::advance(last, std::size_t(count));
+        hpx::parallel::detail::advance(last, static_cast<std::size_t>(count));
         return hpx::parallel::detail::segmented_for_each(
             hpx::parallel::detail::for_each<
                 typename iterator_traits::local_iterator>(),
@@ -287,12 +286,11 @@ namespace hpx { namespace segmented {
             hpx::traits::is_segmented_iterator_v<SegIter>
         )>
     // clang-format on
-    typename hpx::parallel::util::detail::algorithm_result<ExPolicy,
-        SegIter>::type
+    hpx::parallel::util::detail::algorithm_result_t<ExPolicy, SegIter>
     tag_invoke(
         hpx::for_each_n_t, ExPolicy&& policy, SegIter first, Size count, F&& f)
     {
-        static_assert((hpx::traits::is_forward_iterator<SegIter>::value),
+        static_assert((hpx::traits::is_forward_iterator_v<SegIter>),
             "Requires at least input iterator.");
 
         using is_seq = hpx::is_sequenced_execution_policy<ExPolicy>;
@@ -308,11 +306,11 @@ namespace hpx { namespace segmented {
         using iterator_traits = hpx::traits::segmented_iterator_traits<SegIter>;
 
         auto last = first;
-        hpx::parallel::detail::advance(last, std::size_t(count));
+        hpx::parallel::detail::advance(last, static_cast<std::size_t>(count));
         return segmented_for_each(
             hpx::parallel::detail::for_each<
                 typename iterator_traits::local_iterator>(),
             HPX_FORWARD(ExPolicy, policy), first, last, HPX_FORWARD(F, f),
             hpx::identity_v, is_seq());
     }
-}}    // namespace hpx::segmented
+}    // namespace hpx::segmented
diff --git a/libs/full/segmented_algorithms/tests/unit/partitioned_vector_for_each.cpp b/libs/full/segmented_algorithms/tests/unit/partitioned_vector_for_each.cpp
index dcc549ee4b64..45cc47a6345e 100644
--- a/libs/full/segmented_algorithms/tests/unit/partitioned_vector_for_each.cpp
+++ b/libs/full/segmented_algorithms/tests/unit/partitioned_vector_for_each.cpp
@@ -1,4 +1,4 @@
-//  Copyright (c) 2014-2023 Hartmut Kaiser
+//  Copyright (c) 2014-2024 Hartmut Kaiser
 //  Copyright (c) 2017 Ajai V George
 //
 //  SPDX-License-Identifier: BSL-1.0
@@ -134,32 +134,84 @@ void test_for_each_async(
     verify_values_count_async(policy, v, val);
 }
 
+template <typename T>
+struct apply_wrap
+{
+    template <typename T_>
+    void operator()([[maybe_unused]] T_& val) const
+    {
+    }
+
+    hpx::reference_wrapper<hpx::partitioned_vector<T>> v;
+
+    template <typename Archive>
+    void serialize(Archive& ar, unsigned)
+    {
+        // clang-format off
+        ar & v;
+        // clang-format on
+    }
+};
+
+template <typename ExPolicy, typename T>
+void test_for_each_apply(ExPolicy&& policy, hpx::partitioned_vector<T>& v)
+{
+    hpx::for_each(policy, v.begin(), v.end(), apply_wrap<T>{v});
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 template <typename T>
 void for_each_tests(std::vector<hpx::id_type>& localities)
 {
+    //{
+    //    hpx::partitioned_vector<T> v;
+    //    hpx::for_each(v.begin(), v.end(), pfo());
+    //    hpx::for_each(hpx::execution::seq, v.begin(), v.end(), pfo());
+    //    hpx::for_each(hpx::execution::par, v.begin(), v.end(), pfo());
+    //    hpx::for_each(hpx::execution::seq(hpx::execution::task), v.begin(),
+    //        v.end(), pfo())
+    //        .get();
+    //    hpx::for_each(hpx::execution::par(hpx::execution::task), v.begin(),
+    //        v.end(), pfo())
+    //        .get();
+    //}
+
+    constexpr std::size_t length = 12;
+
+    //{
+    //    hpx::partitioned_vector<T> v(
+    //        length, T(0), hpx::container_layout(localities));
+    //    test_for_each(v, T(0));
+    //    test_for_each(hpx::execution::seq, v, T(1));
+    //    test_for_each(hpx::execution::par, v, T(2));
+    //    test_for_each_async(hpx::execution::seq(hpx::execution::task), v, T(3));
+    //    test_for_each_async(hpx::execution::par(hpx::execution::task), v, T(4));
+    //}
+
     {
-        hpx::partitioned_vector<T> v;
-        hpx::for_each(v.begin(), v.end(), pfo());
-        hpx::for_each(hpx::execution::seq, v.begin(), v.end(), pfo());
-        hpx::for_each(hpx::execution::par, v.begin(), v.end(), pfo());
-        hpx::for_each(hpx::execution::seq(hpx::execution::task), v.begin(),
-            v.end(), pfo())
-            .get();
-        hpx::for_each(hpx::execution::par(hpx::execution::task), v.begin(),
-            v.end(), pfo())
-            .get();
+        hpx::partitioned_vector<T> v(
+            length, T(0), hpx::container_layout(localities));
+
+        v.register_as("foreach_test1");
+        test_for_each_apply(hpx::execution::seq, v);
+        test_for_each_apply(hpx::execution::par, v);
     }
 
     {
-        constexpr std::size_t length = 12;
+        std::vector<std::size_t> sizes;
+        sizes.reserve(localities.size());
+
+        for (std::size_t i = 0; i != localities.size(); ++i)
+        {
+            sizes.push_back(length / localities.size());
+        }
+
         hpx::partitioned_vector<T> v(
-            length, T(0), hpx::container_layout(localities));
-        test_for_each(v, T(0));
-        test_for_each(hpx::execution::seq, v, T(1));
-        test_for_each(hpx::execution::par, v, T(2));
-        test_for_each_async(hpx::execution::seq(hpx::execution::task), v, T(3));
-        test_for_each_async(hpx::execution::par(hpx::execution::task), v, T(4));
+            length, T(0), hpx::explicit_container_layout(sizes, localities));
+
+        v.register_as("foreach_test2");
+        test_for_each_apply(hpx::execution::seq, v);
+        test_for_each_apply(hpx::execution::par, v);
     }
 }
 
diff --git a/libs/full/segmented_algorithms/tests/unit/partitioned_vector_inclusive_scan.cpp b/libs/full/segmented_algorithms/tests/unit/partitioned_vector_inclusive_scan.cpp
index 16587be0207b..e56fba6ae927 100644
--- a/libs/full/segmented_algorithms/tests/unit/partitioned_vector_inclusive_scan.cpp
+++ b/libs/full/segmented_algorithms/tests/unit/partitioned_vector_inclusive_scan.cpp
@@ -1,11 +1,12 @@
 //  Copyright (c) 2016 Minh-Khanh Do
-//  Copyright (c) 2022 Hartmut Kaiser
+//  Copyright (c) 2022-2024 Hartmut Kaiser
 //
 //  SPDX-License-Identifier: BSL-1.0
 //  Distributed under the Boost Software License, Version 1.0. (See accompanying
 //  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
 
 #include <hpx/config.hpp>
+
 #if !defined(HPX_COMPUTE_DEVICE_CODE)
 #include <hpx/hpx_main.hpp>
 #include <hpx/include/parallel_scan.hpp>
@@ -33,7 +34,6 @@
               << g << " " << h << " " << i << " ";
 
 ///////////////////////////////////////////////////////////////////////////////
-
 template <typename T>
 struct opt
 {
@@ -322,9 +322,9 @@ template <typename T>
 void inclusive_scan_tests(std::vector<hpx::id_type>& localities)
 {
 #if defined(HPX_DEBUG)
-    std::size_t const length = 1000;
+    constexpr std::size_t length = 1000;
 #else
-    std::size_t const length = 10000;
+    constexpr std::size_t length = 10000;
 #endif
 
     inclusive_scan_tests_with_policy<T>(length, hpx::container_layout);
@@ -357,4 +357,5 @@ int main()
     inclusive_scan_tests<long long>(localities);
     return hpx::util::report_errors();
 }
+
 #endif