简体   繁体   English

有什么办法在成员变量上做std :: upper_bound吗?

[英]Any way to do a std::upper_bound on a member variable?

I want to use std::upper_bound to find the span of objects in some container which are less or equal to a provided value. 我想使用std::upper_bound在某个容器中查找小于或等于提供值的对象范围。 This makes it a nice simple one-liner! 这使其成为一个很好的简单单线!

The problem is I'm interested only in comparing against a specific primitive member of the class. 问题是我只想与类的特定原始成员进行比较。 Sorting the container is no problem, but when I want to use std::upper_bound , I need to provide an object to compare against for the function to work. 对容器进行排序没有问题,但是当我想使用std::upper_bound ,我需要提供一个对象进行比较以使该功能起作用。

For an MCVE, suppose I have a bunch of people and I want to find an iterator to: 对于MCVE,假设我有一堆人,并且想找到一个迭代器来:

struct Person {
    int age;
    double height;

    Person(int age, double height) : age(age), height(height) { }
};

int main() {
    vector<Person> people = { 
        Person(5, 12.3), 
        Person(42, 9.6), 
        Person(38, 18.4), 
        Person(31, 8.5)
    };

    auto sorter = [](const Person& a, const Person& b) {
        return a.height < b.height;
    };

    std::sort(people.begin(), people.end(), sorter);

    // All I care about is comparing against this number
    // Instead... I have to create a whole new struct
    //double cutoff = 10.0;
    Person cutoff(123, 10.0);
    auto it = std::upper_bound(people.begin(), people.end(), cutoff, sorter);

    // Do stuff with 'it' here
}

The problem I have is that I need to instantiate the whole object just to use std::upper_bound , like I do in the code above. 我遇到的问题是,我需要实例化整个对象只是为了使用std::upper_bound ,就像我在上面的代码中所做的那样。 I can't have a 'comparator against the value I'm providing'. 我不能“与我提供的价值进行比较”。 This makes it very annoying because the objects I'm comparing against aren't easy for me to pop into existence without doing a fair amount of work. 这使我非常烦恼,因为要进行比较的对象对于我而言,如果不做大量工作就很难实现。

Are there any viable strategies to get around this that will lead to the cleanest and most compact code I can find? 是否有任何可行的策略可以解决这个问题,从而使我找到最干净,最紧凑的代码? For example, it'd have been nice if I could have done (for the MCVE): 例如,如果我能做的很好(对于MCVE),那就太好了:

auto cutoffCompare = [](const Person& p, const double height) { 
    return p.height < height;
};

// Doesn't exist (AFAIK?)
auto it = std::upper_bound(people.begin(), people.end(), cutoff, sorter, cutoffCompare);

Due to it being in aa hot spot in the program where I care about performance more than normal, I can't do something like transform the objects into the primitive type and then do upper_bound on that new list. 由于它位于程序中的一个热点,在这里我比平时更在乎性能,因此我无法执行将对象转换为原始类型然后在该新列表上进行upper_bound操作。 I can create a whole new object and use it as a dummy, but then I'll be adding an annoying amount of code to do something very simple. 我可以创建一个全新的对象并将其用作虚拟对象,但是随后我将添加大量恼人的代码以完成非常简单的操作。 Am I stuck instantiating the object? 我是否坚持实例化对象? Or do I have to roll my own upper_bound? 还是我必须滚动自己的upper_bound?

There's no requirement that the value passed to std::upper_bound has to match the iterator's type, it could be anything you want if you provide the right comparison function. 不需要传递给std::upper_bound的值必须与迭代器的类型匹配,如果您提供正确的比较函数,则可以是您想要的任何值。 You were pretty close with your desired sample, just need to flip the arguments. 您与所需的样本非常接近,只需要翻转参数即可。 The docs here indicate the comparison function takes in the limit value as the first argument. 此处的文档指示比较函数将限制值作为第一个参数。

auto cutoffCompare = [](double height, const Person& p) { 
    return p.height < height;
};

auto it = std::upper_bound(people.begin(), people.end(), 10.0, cutoffCompare);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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