Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/logging/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么set::find不是模板?_C++_Stl_C++11_Std - Fatal编程技术网

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

C++ 为什么set::find不是模板?,c++,stl,c++11,std,C++,Stl,C++11,Std,使用中的模板函数,您可以执行以下操作 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> // comp

使用
中的模板函数,您可以执行以下操作

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;
}
如果一个人只需调用
foos.find(2)
,那将非常有帮助。有没有什么原因使
find
不能成为一个模板,接受可以传递给less谓词的所有内容。如果它只是丢失了,为什么它不在C++11中(我想不是)

编辑 主要的问题是为什么它不可能,如果它是可行的,为什么决定标准不提供它。第二个问题是您可以提出解决方法:-)(
boost::multi_index_container
刚才我想到了,它提供了从值类型中提取键的功能)

另一个例子是构造值类型的成本更高。键
名称
是类型的一部分,不应在地图键中用作副本

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;

};
struct-Person
{
std::字符串名;
字符串地址;
std::字符串电话、电子邮件、传真、Stackoferflow昵称;
智力年龄;
病媒朋友;
向量关系;
};
结构PersonOrder
{
//假设全名是唯一标识符
布尔运算符()(常数人和左侧、常数人和右侧)常数
{
返回lh.name
key_type是集合容器中定义为key别名的成员类型,key是第一个模板参数,也是容器中存储的元素类型


对于用户定义的类型,库无法知道键类型是什么。恰好对于您的特定用例,键类型是
int
。如果使用
sets
您可以调用
s.find(2)。然而,如果你想搜索
集合
并且只想传入一个整数(想想
集合
的排序在
foo
int
之间是如何工作的),你需要帮助编译器解决这个问题。

他们提供了你想要的,但方式与你所考虑的完全不同

实际上,有两种不同的方法:一种是为包含的类构建构造函数,1)可以隐式使用,2)只需要比较所需的元素子集。有了它,你可以搜索
食物。您将从
2
创建一个临时对象,然后找到该临时对象,但它将是真正的临时对象。您的代码不必显式地(在任何地方)处理它

编辑:我在这里所说的是创建一个与您存储在映射中的类型相同的实例,但是(可能)不初始化(或者初始化为“不存在”)任何未用作“键”的字段。例如:

struct X { 
   int a; // will be treated as the key
   std:::string data;
   std::vector<int> more_data;
public:
   X(int a) : a(a) {} // the "key-only" ctor
   X(int a, std::string const &d, std::vector<int> const &m); // the normal ctor
};

std::set<X> s;

if (s.find(2)) { // will use X::X(int) to construct an `X`
    // we've found what we were looking for
}
struct X{
int a;//将被视为密钥
std:::字符串数据;
std::向量更多的数据;
公众:
X(inta):a(a){}//只包含键的向量
X(int a,std::string const&d,std::vector const&m);//正常的向量
};
std::集s;
if(s.find(2)){//将使用X::X(int)构造一个`X`
//我们找到了我们要找的东西
}
是的,当你用单参数构造函数构造你的
X
(或者我称之为X)时,你所构造的东西很可能除了搜索之外什么都用不上

结束编辑]


第二个,库提供了更直接的支持,通常比较简单:如果您实际上只使用某些元素子集(可能只有一个)进行搜索,那么您可以创建
std::map
,而不是
std::set
。使用
std::map
,显式/直接支持搜索指定为键类型的任何对象的实例。

std::find_如果
在未排序的范围内工作。所以你可以传递任何你想要的谓词

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

因此,如果对
std::set::find
进行模板化,则必须只传递一个观察比较器总顺序的谓词

然后再次强调,
std::lower_bound
和所有其他在排序范围上工作的算法都已经精确地要求了这一点,因此这不是一个新的或令人惊讶的要求

所以,我想这只是一个疏忽,在
std::set
上没有
find_if()
(say)。建议使用C++17:)(EDIT::EASTL,他们使用了一个比我好得多的名字:
find_as

也就是说,你知道吗?排序向量在大多数情况下会更快,并允许您找到
std::set
中缺少的灵活性


编辑:正如Nicol所指出的,在和(以及其他地方,我确信)中有这个概念的实现,但鉴于您无法利用它们的主要优势(内置的
find()
方法),使用裸
std::vector
,您不会损失太多,因为如果您想执行
std::find(2)
除了两个
foo
s之间的比较外,还必须定义
int
如何与
foo
进行比较。但是由于
int
foo
是不同的类型,您实际上需要两个附加函数:

bool operator<(int, foo);
bool operator<(foo, int);

bool操作符标准规定
std::set::find
具有对数时间复杂度。实际上,这是通过将
std::set
实现为二进制搜索树来实现的
bool operator<(int, foo);
bool operator<(foo, int);