一个函数模板,可以根据任何属性

时间:2016-04-09 06:36:01

标签: c++ sorting templates multidimensional-array

我是非常大的公立学校的校长,我一直在看着我的孩子长大了十年。他们每年的基本信息和考试成绩存储如下:

class KidInfo{
    string name;
    int age;
    vector<int> score; //The lengths increases as my kids grows up
};

const int NUM = 100000;  //Wow, that's gigantic my friend

KidInfo myKids[NUM];

现在我想分析这些结果并创建他们的学习档案。要做到这一点,我需要每年按降序排列数组myKids十年。我必须使用std::sort来保证效率,因为我正在经营一所大型学校。

我不是一个非常熟练的C ++程序员,也不知道如何处理这个任务。在检查答案sort multidimensional vector by 1st column后,我写了以下代码:

bool cmpByYear1(const KidInfo &k1, const KidInfo &k2){
    return k1.score[0] > k2.score[0];
}

bool cmpByYear2(const KidInfo &k1, const KidInfo &k2){
    return k1.score[1] > k2.score[1];
}

//And 8 similiar functions

sort(muKids, myKids + NUM, cmpByYear1);
//print Year 1...
sort(muKids, myKids + NUM, cmpByYear2);
//print Year 2, and so on...

在我每年无聊写一个新的cmpByYearN函数之前没花太多时间,所以我在考虑更优雅的方法,比如模板

template<int year>
bool cmpAnyYear(const KidInfo &k1, const KidInfo &k2){
    return k1.score[year - 1] > k2.score[year - 1];
}

int main(){
    //...
    for(int year = 1; year <= 10; ++year){
        sort(myKids, myKids + NUM, cmpAnyYear<year>);
    }
    //...
    return 0;
}

不幸的是,我的代码出现了编译错误,例如 “template parameter "year": local variables cannot be used as non-type parameter...”

所以我想改为使用全局参数:

int globalYear = 1;

bool cmpAnyYear(const KidInfo &k1, const KidInfo &k2){
    return k1.score[globalYear - 1] > k2.score[globalYear - 1];
}

int main(){
    //...
    for(; globalYear <= 10; ++globalYear){
        sort(myKids, myKids + NUM, cmpAnyYear);
    }
    //...
    return 0;
}

这次我的代码实际上运行,但遗憾的是它仍然没有工作:看起来cmpAnyYear功能已经已修复,当我声明globalYear = 1;并且表现得像cmpByYear1时,无论globalYear的后续更改如何。排序结果从第2年开始保持不变。

2 个答案:

答案 0 :(得分:2)

您可以使用仿函数对象,例如

struct cmpAnyYear
{
    cmpAnyYear(int year)
        : year_(year)
    {}

    bool operator()(KindInfo const& k1, KidInfo const& k2) const
    {
        return k1.score[year_ - 1] > k2.score[year_ - 1];
    }

    int year_;
}

int main(){
    //...
    for(int year = 1; year <= 10; ++year){
        sort(myKids, myKids + NUM, cmpAnyYear(year));
    }
    //...
    return 0;
}

表达式cmpAnyYear(year)构造一个cmpAnyYear类型的(临时)对象,并将year作为参数传递给构造函数。该对象是一个“被调用”的函数,它调用cmpAnyYear::operator()进行比较。

答案 1 :(得分:1)

使用捕捉year

的lambda
int main()
{
    //...
    for (int year = 1; year <= 10; ++year) {
        sort(myKids, myKids + NUM, [year](const KidInfo& k1, const KidInfo& k2) {
            return k1.score[year - 1] > k2.score[year - 1];
        });
    }
    //...
    return 0;
}

year作为模板参数不起作用的原因是因为它在您调用它时必须是编译时常量,而不是for loop