@@ -422,6 +422,13 @@ class ReductionIdentityContainer<
422422 static constexpr bool has_identity = false ;
423423};
424424
425+ // Token class to help with the in-place construction of reducers.
426+ template <class BinaryOperation , typename IdentityContainerT>
427+ struct ReducerToken {
428+ const IdentityContainerT &IdentityContainer;
429+ const BinaryOperation BOp;
430+ };
431+
425432} // namespace detail
426433
427434// / Specialization of the generic class 'reducer'. It is used for reductions
@@ -458,6 +465,14 @@ class reducer<
458465 reducer (const IdentityContainerT &IdentityContainer, BinaryOperation BOp)
459466 : MValue(GetInitialValue(IdentityContainer)),
460467 MIdentity (IdentityContainer), MBinaryOp(BOp) {}
468+ reducer (
469+ const detail::ReducerToken<BinaryOperation, IdentityContainerT> &Token)
470+ : reducer(Token.IdentityContainer, Token.BOp) {}
471+
472+ reducer (const reducer &) = delete;
473+ reducer (reducer &&) = delete;
474+ reducer &operator =(const reducer &) = delete ;
475+ reducer &operator =(reducer &&) = delete ;
461476
462477 reducer &combine (const T &Partial) {
463478 if constexpr (has_identity)
@@ -515,6 +530,14 @@ class reducer<
515530 reducer () : MValue(getIdentity()) {}
516531 reducer (const IdentityContainerT & /* Identity */ , BinaryOperation)
517532 : MValue(getIdentity()) {}
533+ reducer (
534+ const detail::ReducerToken<BinaryOperation, IdentityContainerT> &Token)
535+ : reducer(Token.IdentityContainer, Token.BOp) {}
536+
537+ reducer (const reducer &) = delete ;
538+ reducer (reducer &&) = delete ;
539+ reducer &operator =(const reducer &) = delete ;
540+ reducer &operator =(reducer &&) = delete ;
518541
519542 reducer &combine (const T &Partial) {
520543 BinaryOperation BOp;
@@ -553,6 +576,14 @@ class reducer<T, BinaryOperation, Dims, Extent, IdentityContainerT, View,
553576public:
554577 reducer (internal_value_type &Ref, BinaryOperation BOp)
555578 : MElement(Ref), MBinaryOp(BOp) {}
579+ reducer (
580+ const detail::ReducerToken<BinaryOperation, IdentityContainerT> &Token)
581+ : reducer(Token.IdentityContainer, Token.BOp) {}
582+
583+ reducer (const reducer &) = delete ;
584+ reducer (reducer &&) = delete ;
585+ reducer &operator =(const reducer &) = delete ;
586+ reducer &operator =(reducer &&) = delete ;
556587
557588 reducer &combine (const T &Partial) {
558589 if constexpr (has_identity)
@@ -599,6 +630,14 @@ class reducer<
599630 reducer (const IdentityContainerT &IdentityContainer, BinaryOperation BOp)
600631 : MValue(GetInitialValue(IdentityContainer)),
601632 MIdentity (IdentityContainer), MBinaryOp(BOp) {}
633+ reducer (
634+ const detail::ReducerToken<BinaryOperation, IdentityContainerT> &Token)
635+ : reducer(Token.IdentityContainer, Token.BOp) {}
636+
637+ reducer (const reducer &) = delete;
638+ reducer (reducer &&) = delete;
639+ reducer &operator =(const reducer &) = delete ;
640+ reducer &operator =(reducer &&) = delete ;
602641
603642 reducer<T, BinaryOperation, Dims - 1 , Extent, IdentityContainerT, true >
604643 operator [](size_t Index) {
@@ -650,6 +689,14 @@ class reducer<
650689 reducer () : MValue(getIdentity()) {}
651690 reducer (const IdentityContainerT & /* Identity */ , BinaryOperation)
652691 : MValue(getIdentity()) {}
692+ reducer (
693+ const detail::ReducerToken<BinaryOperation, IdentityContainerT> &Token)
694+ : reducer(Token.IdentityContainer, Token.BOp) {}
695+
696+ reducer (const reducer &) = delete ;
697+ reducer (reducer &&) = delete ;
698+ reducer &operator =(const reducer &) = delete ;
699+ reducer &operator =(reducer &&) = delete ;
653700
654701 // SYCL 2020 revision 4 says this should be const, but this is a bug
655702 // see https://github.com/KhronosGroup/SYCL-Docs/pull/252
@@ -746,6 +793,8 @@ class reduction_impl_algo {
746793
747794 using identity_container_type =
748795 ReductionIdentityContainer<T, BinaryOperation, ExplicitIdentity>;
796+ using reducer_token_type =
797+ detail::ReducerToken<BinaryOperation, identity_container_type>;
749798 using reducer_type =
750799 reducer<T, BinaryOperation, Dims, Extent, identity_container_type>;
751800 using result_type = T;
@@ -2062,8 +2111,11 @@ void reduCGFuncMulti(handler &CGH, KernelType KernelFunc,
20622111 // Pass all reductions to user's lambda in the same order as supplied
20632112 // Each reducer initializes its own storage
20642113 auto ReduIndices = std::index_sequence_for<Reductions...>();
2065- auto ReducersTuple = std::tuple{typename Reductions::reducer_type{
2066- std::get<Is>(IdentitiesTuple), std::get<Is>(BOPsTuple)}...};
2114+ auto ReducerTokensTuple =
2115+ std::tuple{typename Reductions::reducer_token_type{
2116+ std::get<Is>(IdentitiesTuple), std::get<Is>(BOPsTuple)}...};
2117+ auto ReducersTuple = std::tuple<typename Reductions::reducer_type...>{
2118+ std::get<Is>(ReducerTokensTuple)...};
20672119 std::apply ([&](auto &...Reducers ) { KernelFunc (NDIt, Reducers...); },
20682120 ReducersTuple);
20692121
0 commit comments