The following function applies a functor on each element and reduces the return value:
template <class FCT, class RED>
RED::TYPE forAllElements(FCT functor, RED reducer){
for(/* all elem in elements */){
reducer(functor(elem));
}
return reducer.value;
}
Now, sometimes I might wish to just call the functor
on all elements, and not reduce anything. Basically, I would then like to have something like:
class FunctorThatReturnsNothing{
void operator() (Elem e){
// do something, return nothing...
}
}
class DummyReducer{
using TYPE = void; // ??? something like that ???
template <class FCT>
void operator() (/* ??? what here */){
// do nothing...
}
}
forAllElements(FunctorThatReturnsNothing(), DummyReducer());
But that won't compile since I have reducer(functor(elem))
where the non-existent return value of a void function is taken as an argument.
Is there a way to make it work for void functors without duplicating forAllElements for a void
and a non-void
case?
(For people suspecting an XY-Problem: I basically know different approaches for iterating and reducing and I think that the presented callback approach is appropriate for my case. I just wonder how I can avoid to have duplicate code for the "return value + reducing" and the "just callback" case.)
I think you can just make a VoidReducer
class, but instead of return reducer.value;
you would need return reducer.getvalue();
. Then you simply make void VoidReducer::getvalue(){}
.
I haven't tested this but the idea should work. You are allowed to return f();
if both f
and the current function have return type void
.
EDIT
Now that I read the question more carefully, I see that the problem you're asking about is the line reducer(functor(elem));
.
For this I would compile-time dispatch based on decltype(functor(elem))
.
template <class Functor, class Reducer, class Elem>
void Combine(Functor functor, Reducer & reducer, Elem elem, std::true_type)
{
functor(elem);
}
template <class Functor, class Reducer, class Elem>
void Combine(Functor functor, Reducer & reducer, Elem elem, std::false_type)
{
reducer(functor(elem));
}
template <class Functor, class Reducer, class Elem>
void Combine(Functor functor, Reducer & reducer, Elem elem)
{
Combine(functor, reducer, elem, std::is_same<decltype(functor(elem)), void>());
}
Then calling Combine
instead of reducer(functor(elem))
will correctly reduce the return value of functor
if and only if it's not void.
PS: Sprinkle references and std::forward
calls to taste.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With