【问题标题】:C++ std::sort() - Unable to sort a vector of a class type that access member variablesC++ std::sort() - 无法对访问成员变量的类类型的向量进行排序
【发布时间】:2015-10-31 07:46:57
【问题描述】:

Entry.h:

//returns the sum of all non mega entry percentages
float sumOfNonMegaEntryPct(vector<Number>& arg1_Numbers);

Entry.cpp:

//returns the sum of all mega entry percentages
float Entry::sumOfMegaEntryPct(vector<MegaNumber>& arg1_MegaNumbers)
{
    float sumPct = 0.00f;
     for (MegaNumber c : megaEntry)
     {
         sumPct = sumPct + arg1_MegaNumbers[c.getID()].getOccurencePct();
     }

     return sumPct;
}

Lotto.h:

public:
//compares two entries, used for sorting algorithm, sorts by nonmega number
bool compareEntry_sumPct_nonMega(Entry arg1, Entry arg2); 

    protected:
    vector<Numbers> numbers;
    vector<MegaNumbers> megaNumbers;

Lotto.cpp:

#include "lotto.h"

//sorts nonmega numbers by sum of their pct, used for sort algorithm
bool Lotto::compareEntry_sumPct_nonMega(Entry arg1, Entry arg2)
{
    bool b = arg1.sumOfNonMegaEntryPct(numbers) < arg2.sumOfNonMegaEntryPct(numbers);
     return b;
}

Source.cpp:

vector<Entry> copyGameEntry = game.getPlayEntry();
sort(copyGameEntry.begin(), copyGameEntry.end(),
     bind(&Lotto::compareEntry_sumPct_nonMega, game));

这只是代码的一部分,但我认为它已经足够有意义了。编译时出现错误:

严重性代码描述项目文件行错误 C2451 条件 'std::_Unforced' 类型的表达式是非法的 Lottery Sort e:\program 文件 (x86)\microsoft visual studio 14.0\vc\include\algorithm 3133

严重性代码描述项目文件行错误 C2675 一元“!”: 'std::_Unforced' 未定义此运算符或转换为 预定义运算符 Lottery Sort e:\program 可接受的类型 文件 (x86)\microsoft visual studio 14.0\vc\include\algorithm 3118

问题:

可能是什么问题?

【问题讨论】:

  • 发布一个几乎可以编译的代码...你认为class Lottery { ... }; 不相关? sumOfNonMegaEntryPct 未声明为成员函数。不重要的是如何在 .h 和 .cpp 文件之间划分代码,您可以在类定义本身中定义成员函数。

标签: c++ function class sorting std


【解决方案1】:

您错误地使用了std::bind。您需要为未绑定的参数使用占位符:

using namespace std::placeholders;
sort(copyGameEntry.begin(), copyGameEntry.end(),
     bind(&Lotto::compareEntry_sumPct_nonMega, game, _1, _2));

注意此绑定表达式将复制game 对象,因此您应该使用std::ref(game) 或只使用&amp;game,以避免不必要的复制。

或者使用 lambda 函数:

sort(copyGameEntry.begin(), copyGameEntry.end(),
     [&game](Entry& l, Entry& r) {
       return game.compareEntry_sumPct_nonMega(l, r);
     });

【讨论】:

    【解决方案2】:

    有调用 std::sort 的替代方法:

    #include <algorithm>
    #include <vector>
    
    struct X
    {
        int value;
        bool operator < (const X& other) const { return value < other.value; }
        static bool less(const X& a, const X& b) { return a.value < b.value; }
    };
    
    struct Holder
    {
        bool less(const X& a, const X& b) const { return a.value < b.value; }
    };
    
    int main ()
    {
        Holder holder;
        std::vector<X> values;
    
        // No stateful comparison
        std::sort(values.begin(), values.end());
    
        // No stateful comparison
        std::sort(values.begin(), values.end(), X::less);
    
        // Stateful comparison
        struct Less {
            const Holder& holder;
            Less(const Holder& holder) : holder(holder) {}
            bool operator ()(const X& a, const X& b) const { return holder.less(a, b); }
        };
        std::sort(values.begin(), values.end(), Less(holder));
    
        // Stateful comparison
        std::sort(values.begin(), values.end(), [&holder](const X& a, const X& b) {
            return holder.less(a, b);
        });
    
        // Stateful comparison
        using namespace std::placeholders;
        std::sort(values.begin(), values.end(), std::bind(&Holder::less, holder, _1, _2));
    }
    

    在您的情况下,您可能缺少 std::placeholders

    【讨论】:

    • 只有最后一行(正确)有用。其他示例不相关,因为它们没有展示如何使用有状态比较函数(它必须是有状态的,因为它需要引用Lotto 对象的numbers 成员)。
    【解决方案3】:

    您的错误与:bind(&amp;Lotto::compareEntry_sumPct_nonMega, game) 有关。

    在调用函数std::bind时需要指定std::placeholders,它将按照指定的顺序替换为被调用、返回的函数对象的参数。

    您可以使用以下try - catch 块进行验证:

    try {
        std::sort(copyGameEntry.begin(), copyGameEntry.end(),
                  bind(&Lotto::compareEntry_sumPct_nonMega, game)
    
    } catch (std::bad_function_call& e) {
        std::cout << "ERROR: Bad function call\n";
    
    }
    

    在您的情况下,您需要添加:

    using namespace std::placeholders;
    auto func_obj = bind(&Lotto::compareEntry_sumPct_nonMega, game, _1, _2);
    

    然后,func_obj (_1, _2) 将在内部由sort() 调用,如下所示:

    func_obj(copyGameEntry[i], copyGameEntry[i+1]);
    

    或者,您可以尝试使用类似:

    struct Holder{
        bool less(const Entry& a, const Entry& b) const { 
            return a.sumOfNonMegaEntryPct(numbers) < b.sumOfNonMegaEntryPct(numbers); 
        }
    } holder;
    
    struct Less {
        const Holder& holder;
        Less(const Holder& holder) : holder(holder) {}
        bool operator ()(const Entry& a, const Entry& b) const { return holder.less(a, b); }
    };
    
    std::sort(copyGameEntry.begin(), copyGameEntry.end(), Less(holder));
    

    【讨论】:

      猜你喜欢
      • 2015-01-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多