std :: set iterator具有相同的键和不同的比较器

时间:2018-05-16 00:33:17

标签: c++ c++11 iterator set language-lawyer

在尝试解决问题时,我开始考虑这个问题 - 考虑到user-defined class和2 comparators,我们假设我们有2套std::set<user_class,comparator_inc>std::set<user_class,comparator_dec> comparators通过增加和减少user_class(或许简单int)中的值来排序。这是我的代码:

#include <iostream>
#include <set>

using std::cout;
using std::endl;
using std::set;

struct A
{
    int val;
};
struct c_inc
{
    bool operator()(const A& first,const A& second) const
    {
        return first.val > second.val;
    }
};
struct c_dec
{
    bool operator()(const A& first,const A& second) const
    {
        return first.val < second.val;
    }
};

int main()
{
    set<A,c_inc> s1;
    set<A,c_dec> s2;

    auto x = s1.insert({1});
    cout << x.first->val << endl;

    x = s2.insert({1});
    x = s2.insert({0});

    cout << x.first->val << endl;   
}

我的问题是:是否定义了将x重新分配给insert的输出到具有相同set但不同比较器的Key的行为?这种用途有问题吗?它是在标准中定义的应该是什么,还是依赖于实现?

由于代码编译我认为两种情况下return类型的insert都是相同的 - 这个假设是正确的吗?

2 个答案:

答案 0 :(得分:8)

我认为它依赖于实现。

从概念上讲,s1.inserts2.insert的返回类型不同;特别是它们有不同的迭代器类型,即std::set<A,c_inc>::iteratorstd::set<A,c_dec>::iterator。如何定义std::set::iterator类型是实现定义的。

[set.overview]/2

using iterator               = implementation-defined; // see [container.requirements]
using const_iterator         = implementation-defined; // see [container.requirements]

答案 1 :(得分:3)

从技术上讲,你不应该依赖于此。

  

由于代码编译我认为两者都是insert的返回类型   案例是一样的 - 这个假设是正确的吗?

不,不是。想象一下这个简单的例子:

template<class T>
struct set {
   struct iterator { /*...*/ };
};

在这种情况下,set<int>::iterator肯定与set<double>::iterator不同。

实现可以自由地将迭代器类型实现为一个自由类(因为迭代器不依赖于比较器),这似乎是主要实现中的情况,并且是什么允许你的例子。