[英]Set the generic return type
我有一个很适合我的功能:
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);
};
该签名是错误的:
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;
还有其他一些可以改进的地方:修改编译器的front元素以减少它。 我认为您想做这样的事情:
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
的定义。
如其他人所述,您不需要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;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.