I’ve a function that works well for me:
template <typename __container, typename __callback = std::function <
void (typename __container::value_type, typename __container::value_type)>
>
int reduce(__container &&container, __callback &&callback)
{
auto current = container.begin();
for (auto value : container)
*current = callback(*current, value);
return *current;
};
int result = functional::reduce(vector, [](const int current, const int next) -> int {
return current + next;
});
std::cout << result; // 10
And now, I’m going to unify the one:
template <typename __container, typename __callback = std::function <
void (typename __container::value_type, typename __container::value_type)>
>
auto reduce(__container &&container, __callback &&callback) ->
decltype(__container::value_type);
However I am getting the following error:
reduce.cpp:61:9: error: no matching function for call to 'reduce'
int i = reduce(vector, [](const int current, const int next) -> int {
^~~~~~~~~~~~~~~~~~
reduce.hpp:69:7: note: candidate template ignored: substitution failure [with __container = std::__1::list<int, std::__1::allocator<int>> &, __callback = <lambda at
nott.cpp:61:36>]
auto reduce(__container &&container, __callback &&callback) -> decltype(__container::value_type)
^
1 error generated.
make: *** [build] Error 1
How can I set the generic return type?
UPDATE:
template <typename __container, typename __callback>
auto reducef(const __container& input, __callback callback) ->
decltype(callback(std::declval<typename __container::value_type>(), std::declval<typename __container::value_type>()))
{
decltype(
callback(
std::declval<typename __container::value_type>(),
std::declval<typename __container::value_type>()
)
) result{};
return std::accumulate(input.begin(), input.end(), result, callback);
};
This signature is wrong:
value_typeis a type and you decltype it. This is likedecltype(int). However,__container::value_typewon’t work either, since the compiler doesn’t know thatvalue_typeis a type. You have to make this explicit usingtypename:There are some further things, that can be improved: You modify the front element of the compiler to reduce it. I think you want to do something like this:
There is yet another bug: the first value gets reduced twice.
Further improvement: Use iterators instead of ranges:
Next question: Why the restriction of not accepting empty ranges? Use an initial value for that.
And, surprise, this is exactly the definition of
std::accumulate.