繁体   English   中英

设置通用返回类型

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM