为什么是set :: find不是模板? [英] Why is set::find not a template?

查看:300
本文介绍了为什么是set :: find不是模板?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用< algorithm> 的模板函数,您可以执行这样的操作

With template functions from <algorithm> you can do things like this

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;
}

std :: set find 的方法你必须传递一个 set :: key_type 类型的对象,虚拟对象。

In std::set methods like find you have to pass an object of type set::key_type which often forces you to create a dummy object.

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

如果可以调用 foos.find )。有什么原因为什么 find 不能是一个模板,接受可以传递给less谓词的一切。如果它只是缺少,为什么不是在C ++ 11(我认为不是)。

It would be so helpful if one can call just foos.find(2). Is there any reason why find can't be a template, accepting everything that can be passed to the less predicate. And if it is just missing, why isn't it in C++11 (I think it isn't).

主要问题是WHY是不是可能,如果它是可行的,为什么决定标准不提供它。 A第二个问题你可以提出解决方法:-)( boost :: multi_index_container 刚刚交叉,这提供了从值类型的密钥提取)

The main question is WHY isn't it possible and if it was posiible, WHY decided the standard not to provide it. A a second question you can propose workarounds :-) (boost::multi_index_container crosses my mind just now, which provides key extraction from value types)

另一个例子,构造价值类型更昂贵。键名称是类型的一部分,不能用作maps键中的副本;

Another Example with a more expensive to construct value type. The key name is part of the type and should not be used as a copy in maps key;

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;

};


推荐答案

std :: find_if 在未排序的范围上工作。因此,您可以传递任何所需的谓词。

std::find_if works on an unsorted range. So you can pass any predicate you want.

std :: set< T> 始终使用 Comparator 模板参数(默认情况下为 std :: less< T> )以维护集合的顺序,

std::set<T> always uses the Comparator template argument (std::less<T> by default) to maintain the order of the collection, as well as find elements again.

因此,如果 std :: set :: find 是模板化的,传递一个观察比较器总排序的谓词。

So if std::set::find was templated, it would have to require that you only pass a predicate that observes the comparator's total ordering.

然后,再次, std :: lower_bound 在分类范围上的工作已经需要完全一样,所以这不会是一个新的或令人惊讶的要求。

Then again, std::lower_bound and all the other algorithms that work on sorted ranges already require exactly that, so that would not be a new or surprising requirement.

所以,我想这只是一个监督,没有 find_if()(说)在 std :: set 。建议为C ++ 17 :)( EDIT::EASTL 已经有这个,他们使用了比我做的更好的名称: find_as )。

So, I guess it's just an oversight that there's no find_if() (say) on std::set. Propose it for C++17 :) (: EASTL already has this, and they used a far better name than I did: find_as).

也就是说,你知道你不应该使用 std :: set ,是吗?在大多数情况下,排序的向量将更快,并且允许您在 std :: set 中缺少的灵活性。

That said, you know that you shouldn't use std::set, do you? A sorted vector will be faster in most cases and allows you the flexibility you find lacking in std::set.

EDIT:正如Nicol所指出的,在 Boost Loki (以及其他地方,我敢肯定),但看到你不能使用他们的主要优势(内置 find()方法),使用裸体 std :: vector 不会损失太多。

As Nicol pointed out, there're implementations of this concept in Boost and Loki (as well as elsewhere, I'm sure), but seeing as you can't use their main advantage (the built-in find() method), you would not lose much by using a naked std::vector.

这篇关于为什么是set :: find不是模板?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆