• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

STEllAR-GROUP / hpx / #863

11 Jan 2023 05:02PM UTC coverage: 86.533% (-0.05%) from 86.582%
#863

push

StellarBot
Merge #6126

6126: Deprecate hpx::parallel::task_block in favor of hpx::experimental::ta… r=hkaiser a=dimitraka



Co-authored-by: kadimitra <kadimitra@ece.auth.gr>

174614 of 201789 relevant lines covered (86.53%)

1954694.49 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

97.37
/libs/core/algorithms/include/hpx/parallel/algorithms/uninitialized_copy.hpp
1
//  Copyright (c) 2014-2022 Hartmut Kaiser
2
//
3
//  SPDX-License-Identifier: BSL-1.0
4
//  Distributed under the Boost Software License, Version 1.0. (See accompanying
5
//  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6

7
/// \file parallel/algorithms/uninitialized_copy.hpp
8

9
#pragma once
10

11
#if defined(DOXYGEN)
12
namespace hpx {
13

14
    /// Copies the elements in the range, defined by [first, last), to an
15
    /// uninitialized memory area beginning at \a dest. If an exception is
16
    /// thrown during the copy operation, the function has no effects.
17
    ///
18
    /// \note   Complexity: Performs exactly \a last - \a first assignments.
19
    ///
20
    /// \tparam InIter      The type of the source iterators used (deduced).
21
    ///                     This iterator type must meet the requirements of an
22
    ///                     input iterator.
23
    /// \tparam FwdIter     The type of the iterator representing the
24
    ///                     destination range (deduced).
25
    ///                     This iterator type must meet the requirements of a
26
    ///                     forward iterator.
27
    ///
28
    /// \param first        Refers to the beginning of the sequence of elements
29
    ///                     the algorithm will be applied to.
30
    /// \param last         Refers to the end of the sequence of elements the
31
    ///                     algorithm will be applied to.
32
    /// \param dest         Refers to the beginning of the destination range.
33
    ///
34
    /// The assignments in the parallel \a uninitialized_copy algorithm invoked
35
    /// without an execution policy object will execute in sequential order in
36
    /// the calling thread.
37
    ///
38
    /// \returns  The \a uninitialized_copy algorithm returns \a FwdIter.
39
    ///           The \a uninitialized_copy algorithm returns the output
40
    ///           iterator to the element in the destination range, one past
41
    ///           the last element copied.
42
    ///
43
    template <typename InIter, typename FwdIter>
44
    FwdIter uninitialized_copy(InIter first, InIter last, FwdIter dest);
45

46
    /// Copies the elements in the range, defined by [first, last), to an
47
    /// uninitialized memory area beginning at \a dest. If an exception is
48
    /// thrown during the copy operation, the function has no effects.
49
    /// Executed according to the policy.
50
    ///
51
    /// \note   Complexity: Performs exactly \a last - \a first assignments.
52
    ///
53
    /// \tparam ExPolicy    The type of the execution policy to use (deduced).
54
    ///                     It describes the manner in which the execution
55
    ///                     of the algorithm may be parallelized and the manner
56
    ///                     in which it executes the assignments.
57
    /// \tparam FwdIter1    The type of the source iterators used (deduced).
58
    ///                     This iterator type must meet the requirements of an
59
    ///                     forward iterator.
60
    /// \tparam FwdIter2    The type of the iterator representing the
61
    ///                     destination range (deduced).
62
    ///                     This iterator type must meet the requirements of a
63
    ///                     forward iterator.
64
    ///
65
    /// \param policy       The execution policy to use for the scheduling of
66
    ///                     the iterations.
67
    /// \param first        Refers to the beginning of the sequence of elements
68
    ///                     the algorithm will be applied to.
69
    /// \param last         Refers to the end of the sequence of elements the
70
    ///                     algorithm will be applied to.
71
    /// \param dest         Refers to the beginning of the destination range.
72
    ///
73
    /// The assignments in the parallel \a uninitialized_copy algorithm invoked
74
    /// with an execution policy object of type \a sequenced_policy
75
    /// execute in sequential order in the calling thread.
76
    ///
77
    /// The assignments in the parallel \a uninitialized_copy algorithm invoked
78
    /// with an execution policy object of type \a parallel_policy or
79
    /// \a parallel_task_policy are permitted to execute in an
80
    /// unordered fashion in unspecified threads, and indeterminately sequenced
81
    /// within each thread.
82
    ///
83
    /// \returns  The \a uninitialized_copy algorithm returns a
84
    ///           \a hpx::future<FwdIter2>, if the execution policy is of type
85
    ///           \a sequenced_task_policy or
86
    ///           \a parallel_task_policy and
87
    ///           returns \a FwdIter2 otherwise.
88
    ///           The \a uninitialized_copy algorithm returns the output
89
    ///           iterator to the element in the destination range, one past
90
    ///           the last element copied.
91
    ///
92
    template <typename ExPolicy, typename FwdIter1, typename FwdIter2>
93
    typename parallel::util::detail::algorithm_result<ExPolicy, FwdIter2>::type
94
    uninitialized_copy(
95
        ExPolicy&& policy, FwdIter1 first, FwdIter1 last, FwdIter2 dest);
96

97
    /// Copies the elements in the range [first, first + count), starting from
98
    /// first and proceeding to first + count - 1., to another range beginning
99
    /// at dest. If an exception is thrown during the copy operation, the
100
    /// function has no effects.
101
    ///
102
    /// \note   Complexity: Performs exactly \a count assignments, if
103
    ///         count > 0, no assignments otherwise.
104
    ///
105
    /// \tparam InIter      The type of the source iterators used (deduced).
106
    ///                     This iterator type must meet the requirements of an
107
    ///                     input iterator.
108
    /// \tparam Size        The type of the argument specifying the number of
109
    ///                     elements to apply \a f to.
110
    /// \tparam FwdIter     The type of the iterator representing the
111
    ///                     destination range (deduced).
112
    ///                     This iterator type must meet the requirements of a
113
    ///                     forward iterator.
114
    ///
115
    /// \param first        Refers to the beginning of the sequence of elements
116
    ///                     the algorithm will be applied to.
117
    /// \param count        Refers to the number of elements starting at
118
    ///                     \a first the algorithm will be applied to.
119
    /// \param dest         Refers to the beginning of the destination range.
120
    ///
121
    /// The assignments in the parallel \a uninitialized_copy_n algorithm
122
    /// invoked without an execution policy object execute in sequential order
123
    /// in the calling thread.
124
    ///
125
    /// \returns  The \a uninitialized_copy_n algorithm returns a
126
    ///           returns \a FwdIter.
127
    ///           The \a uninitialized_copy_n algorithm returns the output
128
    ///           iterator to the element in the destination range, one past
129
    ///           the last element copied.
130
    ///
131
    template <typename InIter, typename Size, typename FwdIter>
132
    FwdIter uninitialized_copy_n(InIter first, Size count, FwdIter dest);
133

134
    /// Copies the elements in the range [first, first + count), starting from
135
    /// first and proceeding to first + count - 1., to another range beginning
136
    /// at dest. If an exception is thrown during the copy operation, the
137
    /// function has no effects.
138
    ///
139
    /// \note   Complexity: Performs exactly \a count assignments, if
140
    ///         count > 0, no assignments otherwise.
141
    ///
142
    /// \tparam ExPolicy    The type of the execution policy to use (deduced).
143
    ///                     It describes the manner in which the execution
144
    ///                     of the algorithm may be parallelized and the manner
145
    ///                     in which it executes the assignments.
146
    /// \tparam FwdIter1    The type of the source iterators used (deduced).
147
    ///                     This iterator type must meet the requirements of a
148
    ///                     forward iterator.
149
    /// \tparam Size        The type of the argument specifying the number of
150
    ///                     elements to apply \a f to.
151
    /// \tparam FwdIter2    The type of the iterator representing the
152
    ///                     destination range (deduced).
153
    ///                     This iterator type must meet the requirements of a
154
    ///                     forward iterator.
155
    ///
156
    /// \param policy       The execution policy to use for the scheduling of
157
    ///                     the iterations.
158
    /// \param first        Refers to the beginning of the sequence of elements
159
    ///                     the algorithm will be applied to.
160
    /// \param count        Refers to the number of elements starting at
161
    ///                     \a first the algorithm will be applied to.
162
    /// \param dest         Refers to the beginning of the destination range.
163
    ///
164
    /// The assignments in the parallel \a uninitialized_copy_n algorithm
165
    /// invoked with an execution policy object of type
166
    /// \a sequenced_policy execute in sequential order in the
167
    /// calling thread.
168
    ///
169
    /// The assignments in the parallel \a uninitialized_copy_n algorithm
170
    /// invoked with an execution policy object of type
171
    /// \a parallel_policy or
172
    /// \a parallel_task_policy are permitted to execute in an
173
    /// unordered fashion in unspecified threads, and indeterminately sequenced
174
    /// within each thread.
175
    ///
176
    /// \returns  The \a uninitialized_copy_n algorithm returns a
177
    ///           \a hpx::future<FwdIter2> if the execution policy is of type
178
    ///           \a sequenced_task_policy or
179
    ///           \a parallel_task_policy and
180
    ///           returns \a FwdIter2 otherwise.
181
    ///           The \a uninitialized_copy_n algorithm returns the output
182
    ///           iterator to the element in the destination range, one past
183
    ///           the last element copied.
184
    ///
185
    template <typename ExPolicy, typename FwdIter1, typename Size,
186
        typename FwdIter2>
187
    typename parallel::util::detail::algorithm_result<ExPolicy, FwdIter2>::type
188
    uninitialized_copy_n(
189
        ExPolicy&& policy, FwdIter1 first, Size count, FwdIter2 dest);
190
}    // namespace hpx
191

192
#else    // DOXYGEN
193

194
#include <hpx/config.hpp>
195
#include <hpx/concepts/concepts.hpp>
196
#include <hpx/functional/detail/tag_fallback_invoke.hpp>
197
#include <hpx/iterator_support/traits/is_iterator.hpp>
198
#include <hpx/type_support/construct_at.hpp>
199

200
#include <hpx/execution/algorithms/detail/is_negative.hpp>
201
#include <hpx/executors/execution_policy.hpp>
202
#include <hpx/parallel/algorithms/detail/dispatch.hpp>
203
#include <hpx/parallel/algorithms/detail/distance.hpp>
204
#include <hpx/parallel/util/cancellation_token.hpp>
205
#include <hpx/parallel/util/detail/algorithm_result.hpp>
206
#include <hpx/parallel/util/detail/clear_container.hpp>
207
#include <hpx/parallel/util/detail/sender_util.hpp>
208
#include <hpx/parallel/util/loop.hpp>
209
#include <hpx/parallel/util/partitioner_with_cleanup.hpp>
210
#include <hpx/parallel/util/result_types.hpp>
211
#include <hpx/parallel/util/zip_iterator.hpp>
212

213
#include <algorithm>
214
#include <cstddef>
215
#include <iterator>
216
#include <memory>
217
#include <type_traits>
218
#include <utility>
219
#include <vector>
220

221
namespace hpx { namespace parallel { inline namespace v1 {
222
    ///////////////////////////////////////////////////////////////////////////
223
    // uninitialized_copy
224
    namespace detail {
225
        /// \cond NOINTERNAL
226

227
        ///////////////////////////////////////////////////////////////////////
228
        template <typename InIter1, typename FwdIter2, typename Cond>
229
        util::in_out_result<InIter1, FwdIter2> sequential_uninitialized_copy(
32✔
230
            InIter1 first, FwdIter2 dest, Cond cond)
231
        {
232
            FwdIter2 current = dest;
32✔
233
            try
234
            {
235
                for (/* */; cond(first, current); (void) ++first, ++current)
185,116✔
236
                {
237
                    hpx::construct_at(std::addressof(*current), *first);
185,100✔
238
                }
185,084✔
239
                return util::in_out_result<InIter1, FwdIter2>{first, current};
16✔
240
            }
16✔
241
            catch (...)
242
            {
243
                for (/* */; dest != current; ++dest)
51,309✔
244
                {
245
                    std::destroy_at(std::addressof(*dest));
51,293✔
246
                }
51,293✔
247
                throw;
16✔
248
            }
16✔
249
        }
32✔
250

251
        ///////////////////////////////////////////////////////////////////////
252
        template <typename InIter1, typename InIter2>
253
        util::in_out_result<InIter1, InIter2> sequential_uninitialized_copy_n(
576✔
254
            InIter1 first, std::size_t count, InIter2 dest,
255
            util::cancellation_token<util::detail::no_data>& tok)
256
        {
257
            return {std::next(first, count),
1,151✔
258
                util::loop_with_cleanup_n_with_token(
576✔
259
                    first, count, dest, tok,
576✔
260
                    [](InIter1 it, InIter2 dest) -> void {
303,867✔
261
                        hpx::construct_at(std::addressof(*dest), *it);
303,969✔
262
                    },
303,969✔
263
                    [](InIter2 dest) -> void {
9,038✔
264
                        std::destroy_at(std::addressof(*dest));
9,038✔
265
                    })};
9,038✔
266
        }
96✔
267

268
        ///////////////////////////////////////////////////////////////////////
269
        template <typename ExPolicy, typename Iter, typename FwdIter2>
270
        typename util::detail::algorithm_result<ExPolicy,
271
            util::in_out_result<Iter, FwdIter2>>::type
272
        parallel_sequential_uninitialized_copy_n(
54✔
273
            ExPolicy&& policy, Iter first, std::size_t count, FwdIter2 dest)
274
        {
275
            if (count == 0)
54✔
276
            {
277
                return util::detail::algorithm_result<ExPolicy,
12✔
278
                    util::in_out_result<Iter, FwdIter2>>::
279
                    get(util::in_out_result<Iter, FwdIter2>{first, dest});
×
280
            }
281

282
            typedef hpx::util::zip_iterator<Iter, FwdIter2> zip_iterator;
283
            typedef std::pair<FwdIter2, FwdIter2> partition_result_type;
284
            typedef
285
                typename std::iterator_traits<FwdIter2>::value_type value_type;
286

287
            util::cancellation_token<util::detail::no_data> tok;
54✔
288

289
            return util::partitioner_with_cleanup<ExPolicy,
54✔
290
                util::in_out_result<Iter, FwdIter2>, partition_result_type>::
291
                call(
292
                    HPX_FORWARD(ExPolicy, policy), zip_iterator(first, dest),
54✔
293
                    count,
54✔
294
                    [tok](zip_iterator t, std::size_t part_size) mutable
3,096✔
295
                    -> partition_result_type {
296
                        using hpx::get;
297
                        auto iters = t.get_iterator_tuple();
576✔
298
                        FwdIter2 dest = get<1>(iters);
576✔
299
                        return std::make_pair(dest,
575✔
300
                            util::get_second_element(
479✔
301
                                sequential_uninitialized_copy_n(
575✔
302
                                    get<0>(iters), part_size, dest, tok)));
576✔
303
                    },
336✔
304
                    // finalize, called once if no error occurred
305
                    [dest, first, count](auto&& data) mutable
228✔
306
                    -> util::in_out_result<Iter, FwdIter2> {
307
                        // make sure iterators embedded in function object that is
308
                        // attached to futures are invalidated
309
                        util::detail::clear_container(data);
30✔
310

311
                        std::advance(first, count);
30✔
312
                        std::advance(dest, count);
30✔
313
                        return util::in_out_result<Iter, FwdIter2>{first, dest};
30✔
314
                    },
315
                    // cleanup function, called for each partition which
316
                    // didn't fail, but only if at least one failed
317
                    [](partition_result_type&& r) -> void {
144✔
318
                        while (r.first != r.second)
144,338✔
319
                        {
320
                            (*r.first).~value_type();
144,194✔
321
                            ++r.first;
144,194✔
322
                        }
323
                    });
144✔
324
        }
54✔
325

326
        ///////////////////////////////////////////////////////////////////////
327
        template <typename IterPair>
328
        struct uninitialized_copy
329
          : public detail::algorithm<uninitialized_copy<IterPair>, IterPair>
330
        {
331
            uninitialized_copy()
26✔
332
              : uninitialized_copy::algorithm("uninitialized_copy")
26✔
333
            {
26✔
334
            }
26✔
335

336
            template <typename ExPolicy, typename InIter1, typename Sent,
337
                typename FwdIter2>
338
            static util::in_out_result<InIter1, FwdIter2> sequential(
12✔
339
                ExPolicy, InIter1 first, Sent last, FwdIter2 dest)
340
            {
341
                return sequential_uninitialized_copy(
12✔
342
                    first, dest, [last](InIter1 first, FwdIter2) -> bool {
91,353✔
343
                        return first != last;
91,333✔
344
                    });
345
            }
8✔
346

347
            template <typename ExPolicy, typename Iter, typename Sent,
348
                typename FwdIter2>
349
            static typename util::detail::algorithm_result<ExPolicy,
350
                util::in_out_result<Iter, FwdIter2>>::type
351
            parallel(ExPolicy&& policy, Iter first, Sent last, FwdIter2 dest)
14✔
352
            {
353
                return parallel_sequential_uninitialized_copy_n(
14✔
354
                    HPX_FORWARD(ExPolicy, policy), first,
14✔
355
                    detail::distance(first, last), dest);
14✔
356
            }
4✔
357
        };
358
        /// \endcond
359
    }    // namespace detail
360

361
    /////////////////////////////////////////////////////////////////////////////
362
    // uninitialized_copy_sent
363
    namespace detail {
364
        /// \cond NOINTERNAL
365
        template <typename IterPair>
366
        struct uninitialized_copy_sent
367
          : public detail::algorithm<uninitialized_copy_sent<IterPair>,
368
                IterPair>
369
        {
370
            uninitialized_copy_sent()
40✔
371
              : uninitialized_copy_sent::algorithm("uninitialized_copy_sent")
40✔
372
            {
40✔
373
            }
40✔
374

375
            template <typename ExPolicy, typename InIter1, typename Sent1,
376
                typename FwdIter2, typename Sent2>
377
            static util::in_out_result<InIter1, FwdIter2> sequential(ExPolicy,
20✔
378
                InIter1 first, Sent1 last, FwdIter2 dest, Sent2 last_d)
379
            {
380
                return sequential_uninitialized_copy(first, dest,
32✔
381
                    [last, last_d](InIter1 first, FwdIter2 current) -> bool {
93,811✔
382
                        return !(first == last || current == last_d);
93,783✔
383
                    });
384
            }
8✔
385

386
            template <typename ExPolicy, typename Iter, typename Sent1,
387
                typename FwdIter2, typename Sent2>
388
            static typename util::detail::algorithm_result<ExPolicy,
389
                util::in_out_result<Iter, FwdIter2>>::type
390
            parallel(ExPolicy&& policy, Iter first, Sent1 last, FwdIter2 dest,
20✔
391
                Sent2 last_d)
392
            {
393
                std::size_t dist1 = detail::distance(first, last);
24✔
394
                std::size_t dist2 = detail::distance(dest, last_d);
20✔
395
                std::size_t dist = dist1 <= dist2 ? dist1 : dist2;
20✔
396

397
                return parallel_sequential_uninitialized_copy_n(
20✔
398
                    HPX_FORWARD(ExPolicy, policy), first, dist, dest);
20✔
399
            }
4✔
400
        };
401
        /// \endcond
402
    }    // namespace detail
403

404
    /////////////////////////////////////////////////////////////////////////////
405
    // uninitialized_copy_n
406
    namespace detail {
407
        /// \cond NOINTERNAL
408
        template <typename IterPair>
409
        struct uninitialized_copy_n
410
          : public detail::algorithm<uninitialized_copy_n<IterPair>, IterPair>
411
        {
412
            uninitialized_copy_n()
38✔
413
              : uninitialized_copy_n::algorithm("uninitialized_copy_n")
38✔
414
            {
38✔
415
            }
38✔
416

417
            template <typename ExPolicy, typename InIter, typename FwdIter2>
418
            static util::in_out_result<InIter, FwdIter2> sequential(
18✔
419
                ExPolicy, InIter first, std::size_t count, FwdIter2 dest)
420
            {
421
                FwdIter2 current = dest;
18✔
422
                try
423
                {
424
                    for (/* */; count > 0; ++first, (void) ++current, --count)
119,237✔
425
                    {
426
                        hpx::construct_at(std::addressof(*current), *first);
119,227✔
427
                    }
119,219✔
428
                    return util::in_out_result<InIter, FwdIter2>{
30✔
429
                        first, current};
20✔
430
                }
8✔
431
                catch (...)
432
                {
433
                    for (/* */; dest != current; ++dest)
44,723✔
434
                    {
435
                        std::destroy_at(std::addressof(*dest));
44,715✔
436
                    }
44,715✔
437
                    throw;
8✔
438
                }
8✔
439
            }
16✔
440

441
            template <typename ExPolicy, typename Iter, typename FwdIter2>
442
            static typename util::detail::algorithm_result<ExPolicy,
443
                util::in_out_result<Iter, FwdIter2>>::type
444
            parallel(
20✔
445
                ExPolicy&& policy, Iter first, std::size_t count, FwdIter2 dest)
446
            {
447
                return parallel_sequential_uninitialized_copy_n(
20✔
448
                    HPX_FORWARD(ExPolicy, policy), first, count, dest);
20✔
449
            }
4✔
450
        };
451
        /// \endcond
452
    }    // namespace detail
453
}}}      // namespace hpx::parallel::v1
454

455
namespace hpx {
456
    ///////////////////////////////////////////////////////////////////////////
457
    // CPO for hpx::uninitialized_copy
458
    inline constexpr struct uninitialized_copy_t final
459
      : hpx::detail::tag_parallel_algorithm<uninitialized_copy_t>
460
    {
461
        // clang-format off
462
        template <typename InIter, typename FwdIter,
463
            HPX_CONCEPT_REQUIRES_(
464
                hpx::traits::is_iterator<InIter>::value &&
465
                hpx::traits::is_forward_iterator<FwdIter>::value
466
            )>
467
        // clang-format on
468
        friend FwdIter tag_fallback_invoke(
469
            hpx::uninitialized_copy_t, InIter first, InIter last, FwdIter dest)
470
        {
471
            static_assert(hpx::traits::is_input_iterator<InIter>::value,
472
                "Required at least input iterator.");
473
            static_assert(hpx::traits::is_forward_iterator<FwdIter>::value,
474
                "Requires at least forward iterator.");
475

476
            return parallel::util::get_second_element(
477
                hpx::parallel::v1::detail::uninitialized_copy<
478
                    parallel::util::in_out_result<InIter, FwdIter>>()
479
                    .call(hpx::execution::seq, first, last, dest));
480
        }
481

482
        // clang-format off
483
        template <typename ExPolicy, typename FwdIter1, typename FwdIter2,
484
            HPX_CONCEPT_REQUIRES_(
485
                hpx::is_execution_policy<ExPolicy>::value &&
486
                hpx::traits::is_forward_iterator<FwdIter1>::value &&
487
                hpx::traits::is_forward_iterator<FwdIter2>::value
488
            )>
489
        // clang-format on
490
        friend typename parallel::util::detail::algorithm_result<ExPolicy,
491
            FwdIter2>::type
492
        tag_fallback_invoke(hpx::uninitialized_copy_t, ExPolicy&& policy,
26✔
493
            FwdIter1 first, FwdIter1 last, FwdIter2 dest)
494
        {
495
            static_assert(hpx::traits::is_forward_iterator<FwdIter1>::value,
496
                "Requires at least forward iterator.");
497
            static_assert(hpx::traits::is_forward_iterator<FwdIter2>::value,
498
                "Requires at least forward iterator.");
499

500
            return parallel::util::get_second_element(
26✔
501
                hpx::parallel::v1::detail::uninitialized_copy<
18✔
502
                    parallel::util::in_out_result<FwdIter1, FwdIter2>>()
503
                    .call(HPX_FORWARD(ExPolicy, policy), first, last, dest));
18✔
504
        }
×
505

506
    } uninitialized_copy{};
507

508
    ///////////////////////////////////////////////////////////////////////////
509
    // CPO for hpx::uninitialized_copy_n
510
    inline constexpr struct uninitialized_copy_n_t final
511
      : hpx::detail::tag_parallel_algorithm<uninitialized_copy_n_t>
512
    {
513
        // clang-format off
514
        template <typename InIter, typename Size,
515
            typename FwdIter,
516
            HPX_CONCEPT_REQUIRES_(
517
                hpx::traits::is_iterator<InIter>::value &&
518
                hpx::traits::is_forward_iterator<FwdIter>::value
519
            )>
520
        // clang-format on
521
        friend FwdIter tag_fallback_invoke(
522
            hpx::uninitialized_copy_n_t, InIter first, Size count, FwdIter dest)
523
        {
524
            static_assert(hpx::traits::is_input_iterator<InIter>::value,
525
                "Required at least input iterator.");
526
            static_assert(hpx::traits::is_forward_iterator<FwdIter>::value,
527
                "Requires at least forward iterator.");
528

529
            // if count is representing a negative value, we do nothing
530
            if (hpx::parallel::v1::detail::is_negative(count))
531
            {
532
                return dest;
533
            }
534

535
            return parallel::util::get_second_element(
536
                hpx::parallel::v1::detail::uninitialized_copy_n<
537
                    parallel::util::in_out_result<InIter, FwdIter>>()
538
                    .call(
539
                        hpx::execution::seq, first, std::size_t(count), dest));
540
        }
541

542
        // clang-format off
543
        template <typename ExPolicy, typename FwdIter1, typename Size, typename FwdIter2,
544
            HPX_CONCEPT_REQUIRES_(
545
                hpx::is_execution_policy<ExPolicy>::value &&
546
                hpx::traits::is_forward_iterator<FwdIter1>::value &&
547
                hpx::traits::is_forward_iterator<FwdIter2>::value
548
            )>
549
        // clang-format on
550
        friend typename parallel::util::detail::algorithm_result<ExPolicy,
551
            FwdIter2>::type
552
        tag_fallback_invoke(hpx::uninitialized_copy_n_t, ExPolicy&& policy,
26✔
553
            FwdIter1 first, Size count, FwdIter2 dest)
554
        {
555
            static_assert(hpx::traits::is_forward_iterator<FwdIter1>::value,
556
                "Requires at least forward iterator.");
557
            static_assert(hpx::traits::is_forward_iterator<FwdIter2>::value,
558
                "Requires at least forward iterator.");
559

560
            // if count is representing a negative value, we do nothing
561
            if (hpx::parallel::v1::detail::is_negative(count))
562
            {
563
                return parallel::util::detail::algorithm_result<ExPolicy,
564
                    FwdIter2>::get(HPX_MOVE(dest));
565
            }
566

567
            return parallel::util::get_second_element(
26✔
568
                hpx::parallel::v1::detail::uninitialized_copy_n<
18✔
569
                    parallel::util::in_out_result<FwdIter1, FwdIter2>>()
570
                    .call(HPX_FORWARD(ExPolicy, policy), first,
52✔
571
                        std::size_t(count), dest));
18✔
572
        }
×
573

574
    } uninitialized_copy_n{};
575
}    // namespace hpx
576

577
#endif    // DOXYGEN
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc