【问题标题】:template class with lambda带有 lambda 的模板类
【发布时间】:2019-10-13 17:45:33
【问题描述】:

假设您对向量或数组的每个元素进行操作。还假设我们要计算所有“满足”某个谓词的元素。

因为 lambda 必须有状态,我们可以这样做:

#include <cstdint>
#include <functional>

template<typename T, class F>
class CountAcummulator{
    size_t count = 0;

    F f;

public:
    constexpr CountAcummulator(F f) : f(std::move(f)){}

    constexpr void operator()(T const &a){
        if (std::invoke(f, a))
            ++count;
    }

    constexpr size_t get() const{
        return count;
    }
};

int main(){
    int x[] = { 1, 2, 3, 4, 5 };

    auto f = [](int a){
        return a > 3;
    };

    CountAcummulator<int, decltype(f)> ca{ f };

    for(auto i : x){
        // do something
        ca(i);
    }

    return ca.get();
}

链接:https://gcc.godbolt.org/z/pjtcCG

不幸的是,我发现这很难使用。如果我们添加投影(另一个 lambda),这个类将无法使用。

有什么办法可以改进这个类以使其可用?

【问题讨论】:

  • 当然可以,但是假设我们在对数组进行 for_each 的同时进行其他一些处理。
  • 查看示例实现并模仿它。您不需要自定义类来实现此算法。
  • 假设我有对象向量,我需要做几个 count_if、min、max、sum(累积)并删除一些 uniq_ptr。我需要一次性完成。
  • 您想要改进什么?如果您只想进行一般性批评,这可能是错误的网站。

标签: c++ templates lambda c++17


【解决方案1】:

有一种称为std::count_if 的标准算法可以计算所有满足谓词的元素。除非您有充分的理由不这样做,否则这应该是首选方法。

#include <algorithm>

int main(){
    int x[] = { 1, 2, 3, 4, 5 };

    auto f = [](int a){
        return a > 3;
    };

    return std::count_if(std::begin(x), std::end(x), f);
}

【讨论】:

  • 然而,count_if 可以一次计算一件事。如果我想找到 10 个不同的计数并同时做一些昂贵的工作怎么办。另外,如果迭代器也很昂贵并且迭代器的前进速度很慢怎么办?
  • @Nick 我可能会使用 std::accumulate 一次计算多个事物。我不明白拥有慢速迭代器有什么意义——无论你做什么,你都必须遍历它们一次。没有算法可以避免必须访问每个元素一次。
  • 如果迭代器很慢,3x 计数将花费 3x 更多的时间。关于累积,我可以在 std::touple 中累积?
  • 你可以使用任何类型作为累加器,包括元组。
猜你喜欢
  • 1970-01-01
  • 2021-04-15
  • 1970-01-01
  • 2015-05-12
  • 1970-01-01
  • 2019-11-13
  • 2013-05-11
  • 2011-08-25
  • 2012-12-07
相关资源
最近更新 更多