如何总结std :: set的元素

时间:2016-01-16 19:54:42

标签: c++ sum numeric stdset accumulate

我试图找到一组中的元素总和,我想知道找到它的好方法是什么。 我构建了两个类,一个名为Customer,一个名为Item,我想编写一个函数来计算客户需要为类型Item中的std :: set中列出的产品支付的总付款。 这是我的集合的解除:

set<Item> _items;

班级项目:

private:
    string _name;
    string _serialNumber; //consists of 5 numbers
    int _count=0; //default is 1, can never be less than 1!
    double _unitPrice; //always bigger than 0!

类Item中的函数总结项目的价格:

double Item :: totalPrice() const
{
    return _count*_unitPrice;
} 

以下是我试图编写的函数,它将汇总我的所有元素:

#include <numeric>
#include "Customer.h"
double Customer::totalSum() const
{
    double sum = std::accumulate(_items.begin(), _items.end(), 0.0);
    return sum;
}

但是我收到了这个错误:error C2893: Failed to specialize function template 'unknown-type std::plus<void>::operator ()(_Ty1 &&,_Ty2 &&) const'

重要注意事项:Customer类已包含Item的标题。

编辑:添加了有关课程项目的信息。

5 个答案:

答案 0 :(得分:3)

假设Item是这样的:

struct Item {
    double price;
};

然后您可以使用以下内容:

auto add_item_price = [](double sum, const Item& item) {
    return sum + item.price;
};

double sum = std::accumulate(_items.begin(), _items.end(), 0.0, add_item_price);

Here's a functional demo

说明:

std::accumulate允许您提供将执行累积的函数/函子。我发布的代码使用lambda function进行累积。如果您没有使用C ++ 11,则可以使用常规函数而不是lambda函数。

避免operator+ Item超载。添加两个Item并没有多大意义。

答案 1 :(得分:0)

当编译器不知道如何累积您的类型时,通常会发生此错误。即它应该知道如何添加Item类型。 因此,您应该在+课程中重载Item运算符。
或者你必须提供第四个参数binary_op

答案 2 :(得分:0)

您需要为operator+()类型指定Item

另请注意,您需要operator<()Item个对象放入std::set,因为它是一个需要能够比较其对象的关联容器:

#include <iostream>
#include <set>
#include <algorithm>

struct Item
{
    Item(double price) : m_price(price) {}

    friend double operator+(const Item &lhs, const Item &rhs)
    {
        return lhs.m_price + rhs.m_price;
    }

    friend double operator<(const Item &lhs, const Item &rhs)
    {
        return lhs.m_price < rhs.m_price;
    }

    double m_price;
};

int main ()
{
    std::set<Item> _items;
    _items.insert( Item(10) );
    _items.insert( Item(20) );
    double sum = std::accumulate(_items.begin(), _items.end(), 0.0);
    std::cout << "Sum = " << sum << std::endl;
    return 0;
}

输出:

Sum = 30

答案 3 :(得分:0)

由于编译器在调用std::accumulate期间不知道如何将两个Item类型的对象一起添加而导致错误。

最简单的解决方案是使用std::accumulate的重载,它接受第四个参数,指定一个lambda仿函数来代替默认的std::plus<T>函数对象。

double Customer::totalSum() const {
    return std::accumulate(_items.begin(), _items.end(), 0.0,
        [] (double previousValue, const auto& item) { // Called for every element.
            return previousValue + item.totalPrice();
        });
}

另一个解决方案是为operator+创建一个自定义重载,可以添加两个Item个对象。

double operator+(const Item& lhs, const Item& rhs) {
    return lhs.totalPrice() + rhs.totalPrice();
}

然而,这可能有点令人困惑,因为类Item有多个成员是数字,并且不应该如何进行添加。重载算术运算符时要特别小心。

答案 4 :(得分:0)

我是唯一一个考虑使用简单循环的人吗?

auto sum = 0.0;
for (const auto& item : items){
   sum += item.m_price;
}
你可以问一下比这简单吗?