我有一个适合我的功能:
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
现在,我要统一一个:
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);
但是我收到以下错误:
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
如何设置通用返回类型?
更新
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);
};
答案 0 :(得分:4)
此签名错误:
auto reduce(__container &&container, __callback &&callback) ->
decltype(__container::value_type);
value_type
是一种类型,您可以对其进行分类。这就像decltype(int)
。但是,__container::value_type
也不起作用,因为编译器不知道value_type
是一种类型。您必须使用typename
:
auto reduce(__container &&container, __callback &&callback) ->
typename __container::value_type;
还有一些可以改进的东西:修改编译器的前端元素以减少它。我想你想做这样的事情:
auto current = *container.begin(); // added *
for (auto value : container)
current = callback(*current, value); // removed *
return current; // removed *
还有另一个错误:第一个值减少两次。
assert(!container.empty());
auto current = *container.begin();
for (auto it=container.begin()+1; it!=container.end(); ++it)
current = callback(current, *it);
return current;
进一步改进:使用迭代器而不是范围:
template <typename Iter, typename Callback>
T reduce(Iter start, Iter end, Callback&& F)
{
assert(start != end);
auto current = *start;
while (++start != end)
current = callback(current, *it);
return *current;
};
下一个问题:为什么限制不接受空范围?使用初始值。
template <typename Iter, typename T, typename Callback>
T reduce(Iter start, Iter end, T init, Callback&& F)
{
while (start != end)
init = callback(init, *it++);
return init;
};
而且,令人惊讶的是,这正是std::accumulate
的定义。
答案 1 :(得分:1)
正如其他人所说,你不需要decltype
。您也不需要auto
。保持代码与您的代码一致(因为样式不是手头的问题),这是一个工作版本:
#include <iostream>
#include <vector>
template <typename Container, typename Callback>
typename Container::value_type reduce(Container &container, Callback &&cb) {
auto current = container.begin();
for (auto value : container)
*current = cb(*current, value);
return *current;
}
int main() {
std::vector<int> v = {1, 2, 3};
int result = reduce(v, [](const int current, const int next) -> int {
return current + next;
});
std::cout << "result = " << result << std::endl;
}