为什么set :: find不是模板?

han*_*aad 6 c++ stl std c++11

使用模板函数,<algorithm>您可以执行此类操作

struct foo
{
    int bar, baz;
};

struct bar_less
{
    // compare foo with foo
    bool operator()(const foo& lh, const foo& rh) const
    {
        return lh.bar < rh.bar;
    }
    template<typename T>  // compare some T with foo
    bool operator()(T lh, const foo& rh) const
    {
        return lh < rh.bar;
    }
    template<typename T>  // compare foo with some T
    bool operator()(const foo& lh, T rh) const
    {
        return lh.bar < rh;
    }
};

int main()
{
    foo foos[] = { {1, 2}, {2, 3}, {4, 5} };
    bar_less cmp;
    int bar_value = 2;
    // find element {2, 3} using an int
    auto it = std::lower_bound(begin(foos), end(foos), bar_value, cmp);
    std::cout << it->baz;
}
Run Code Online (Sandbox Code Playgroud)

std::set类似的方法中,find您必须传递一个类型的对象,set::key_type这通常会强制您创建一个虚拟对象.

set<foo> foos;
foo search_dummy = {2,3};  // don't need a full foo object;
auto it = foos.find(search_dummy);
Run Code Online (Sandbox Code Playgroud)

如果一个人可以打电话,那会很有帮助foos.find(2).是否有任何理由find不能成为模板,接受可以传递给较少谓词的所有内容.如果它只是缺失,为什么不在C++ 11中(我认为它不是).

编辑

主要问题是为什么不可能,如果它是可能的,为什么决定不提供它的标准.第二个问题,你可以建议解决方法:-)(boost::multi_index_container刚刚思考,提供从值类型的关键提取)

另一个具有更昂贵的构造值类型的示例.键name是该类型的一部分,不应在map键中用作副本;

struct Person
{
    std::string name;
    std::string adress;
    std::string phone, email, fax, stackoferflowNickname;
    int age;
    std::vector<Person*> friends;
    std::vector<Relation> relations;
};

struct PersonOrder
{
    // assume that the full name is an unique identifier
    bool operator()(const Person& lh, const Person& rh) const
    {
        return lh.name < rh.name;
    }
};

class PersonRepository
{
public:

    const Person& FindPerson(const std::string& name) const
    {
        Person searchDummy;  // ouch
        searchDummy.name = name;
        return FindPerson(searchDummy);
    }

    const Person& FindPerson(const Person& person) const;

private:
    std::set<Person, PersonOrder> persons_;
    // what i want to avoid
    // std::map<std::string, Person> persons_;
    // Person searchDummyForReuseButNotThreadSafe;

};
Run Code Online (Sandbox Code Playgroud)

Mar*_*utz 3

std::find_if适用于未排序的范围。所以你可以传递任何你想要的谓词。

std::set<T>始终使用Comparator模板参数(std::less<T>默认情况下)来维护集合的顺序,以及再次查找元素。

因此,如果std::set::find是模板化的,则必须要求您仅传递观察比较器总排序的谓词。

话又说回来,std::lower_bound所有其他适用于排序范围的算法已经完全要求这一点,所以这不会是一个新的或令人惊讶的要求。

所以,我想这只是一个疏忽,没有find_if()(比如说)std::set。建议将其用于 C++17:)(编辑:: EASTL已经有了这个,并且他们使用了一个比我更好的名称:)find_as

也就是说,您知道不应该使用std::set,是吗?在大多数情况下,排序的向量会更快,并为您提供std::set.

编辑:正如 Nicol 指出的,这个概念在BoostLoki中都有实现(我确信还有其他地方),但是由于您无法使用它们的主要优势(内置find()方法),因此您使用裸体不会损失太多std::vector