[libcxx-commits] [libcxx] [libc++][PSTL] Add backend for forwaring to mem functions (PR #102448)

Louis Dionne via libcxx-commits libcxx-commits at lists.llvm.org
Thu Aug 15 09:41:36 PDT 2024


================
@@ -0,0 +1,94 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP___PSTL_BACKENDS_FORWARD_TO_MEM_FUNCS_H
+#define _LIBCPP___PSTL_BACKENDS_FORWARD_TO_MEM_FUNCS_H
+
+#include <__algorithm/copy_move_common.h>
+#include <__algorithm/equal.h>
+#include <__config>
+#include <__pstl/backend_fwd.h>
+#include <__pstl/dispatch.h>
+#include <optional>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#  pragma GCC system_header
+#endif
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+namespace __pstl {
+
+template <class _ExecutionPolicy>
+struct __copy<__forward_to_mem_funcs_backend_tag, _ExecutionPolicy> {
+  template <class _Policy,
+            class _In,
+            class _Out,
+            enable_if_t<__can_lower_copy_assignment_to_memmove<_In, _Out>::value, int> = 0>
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<_Out*>
+  operator()(_Policy&&, _In* __first, _In* __last, _Out* __result) const noexcept {
+    return std::__constexpr_memmove(__result, __first, __element_count(__last - __first));
+  }
----------------
ldionne wrote:

I would like to drive towards something like this:

```c++
  template <class _Policy, class _InputIterator, class _OutputIterator>
  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<_OutputIterator>
  operator()(_Policy&&, _InputIterator __first, _InputIterator __last, _OutputIterator __result) const noexcept {
    using _In = typename iterator_traits<_InputIterator>::value_type;
    using _Out = typename iterator_traits<_OutputIterator>::value_type;

    if constexpr (__can_lower_copy_assignment_to_memmove<_In, _Out>::value && contiguous_iterator<whatever>) {
      return std::__constexpr_memmove(std::__to_address(__result), std::__to_address(__first), __element_count(__last - __first));
    } else {
      using _NextBackend = __find_next_backend<__current_configuration, __forward_to_mem_funcs_backend_tag>; // This basically gives you the first backend that has an implementation for this algo after __forward_to_mem_funcs_backend_tag.
    }
  }
```

This makes it less likely that invalid SFINAE will silently result in this implementation being skipped. I would also really really like to keep a single level of specialization+tag based dispatching, instead of also bringing in SFINAE of the `operator()` itself.

I think we might need to do something like:

```c++
template <class _ExecutionPolicy, class _BackendConfiguration>
struct __copy<__forward_to_mem_funcs_backend_tag, _ExecutionPolicy, _BackendConfiguration> {
  // Use _BackendConfiguration to dispatch to the next. That backend configuration represents the cursor within the `__backend_configuration<...>` object, basically.
};
```

Alternatively, we can also decide to bundle multiple things in a single template parameter, which might make things more future proof:

```c++
template <class _DispatchArguments>
struct __copy<__forward_to_mem_funcs_backend_tag, _DispatchArguments> {
  // Use _DispatchArguments::__backend_configuration
  // or _DispatchArguments::__execution_policy
  // or maybe more in the future.
};
```


https://github.com/llvm/llvm-project/pull/102448


More information about the libcxx-commits mailing list