I have a class which basically just manages a vector of custom types. To relieve me from writing the same iteration loop over and over again I wrote the following construct:
template<typename T>
uint64_t ACCUMULATE_ON_VECTOR(const std::vector<MyClass*> vec, T method)
{
return std::accumulate(vec.begin(), vec.end(), 0, [&](uint64_t acc, const MyClass* c)
{
return acc + (c ? method(c) : 0);
});
}
which is then called like this:
ACCUMULATE_ON_VECTOR(_myVec, std::bind(&MyClass::someMethod, std::placeholders::_1));
This works very well in concept but since I have a lot of methods returning different integer types (signed/unsigned, signed/unsigned long), I'd like to abstract away the for now hardcoded uint64_t cause I get compiler warnings all over the place. For this I somehow need to get the return type of the bind object. Can I somehow do this with decltype? What I'm looking for is this:
template<typename T>
<new deduced type> ACCUMULATE_ON_VECTOR(const std::vector<MyClass*> vec, T method)
{
return std::accumulate(vec.begin(), vec.end(), 0, [&](<new deduced type> acc, const MyClass* c)
{
return acc + (c ? method(c) : 0);
});
}
You can do this using std::result_of
:
template<typename Func>
typename std::result_of<Func(MyClass*)>::type
ACCUMULATE_ON_VECTOR(const std::vector<MyClass*> &vec, Func method)
{
using ResultType = typename std::result_of<Func(MyClass*)>::type;
return std::accumulate(vec.begin(), vec.end(), ResultType{},
[&](typename std::result_of<Func(MyClass*)>::type acc,
const MyClass* c)
{
return acc + (c ? method(c) : ResultType{});
});
}
Note I'm value-initializing the return type instead of using the integer literal zero.
It might be more readable to wrap the function parameter in a std::function<ResultT(MyClass*)>
: the accumulate function would be directly templated on the result type, pushing responsibility for that up to the call site.
BTW, you don't need the auto
/trailing return type technique here, because the return type doesn't depend on the argument list, only on the template parameter - nevertheless, I think it looks slightly nicer:
template<typename Func>
auto ACCUMULATE_ON_VECTOR(const std::vector<MyClass*> &vec,
Func method)
-> typename std::result_of<Func(MyClass*)>::type
{
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