将 equal_range 与bind2nd 和binary_function 结合起来

发布于 2024-08-23 01:41:01 字数 1274 浏览 4 评论 0原文

的排序集合,

class Thing
{
public:
   item a;
   item b;
   other data;
};

vector<Thing> Things;

我有一个使用

class MultiValuedComparator
{
public:
   item a;
   item b;

   MultiValuedComparator(item c, item d)
   {
      a = c;
      b = d;
   }
};

因为我有项目 a 和项目 b 的重复项(但没有其他数据),所以我想获取与项目 a 和项目 b 匹配的一系列数据结构。该集合仅按项目 a 排序。

我认为 equal_range 是执行此操作的合适方法。由于我需要匹配多个从binary_function 继承的项目。

struct RangeByA : public std::binary_function<Thing, MultiValuedComparator>
{
   bool operator()(const Thing &left, const MultiValuedComparator &right)
   {
      return left.a == right.a && left.b == right.b;
   }
}

我不知道如何编写 equal_range 函数,所以它会这样做。我尝试过:

void somefunction()
{
   typedef pair<vector<Thing>::iterator, 
                vector<Thing>::iterator> startEndIterPair;

   MultiValuedComparator mvc(1, 2);

   startEndIterPair p = equal_range
      (
      Things.start(), 
      Things.end(), 
      std::bind2nd(RangeByA, mvc)
      );
}

但是这段代码抱怨“operator<”不匹配在 '__middle.__gnu_cxx::__normal_iterator .. 等中调用 equal_range 时,

我该如何编写这个以便 equal_range 起作用?我不知道在哪里放置重载运算符。 RangeByA似乎不接受它。

I have a sorted collection of

class Thing
{
public:
   item a;
   item b;
   other data;
};

vector<Thing> Things;

using

class MultiValuedComparator
{
public:
   item a;
   item b;

   MultiValuedComparator(item c, item d)
   {
      a = c;
      b = d;
   }
};

Since I have duplicates of item a, and item b (but not other data), I want to grab a range of those data structures that match item a AND item b. The collection is sorted by item a only.

I thought equal_range would be an appropriate method to do this. Since I needed to match more than one item I inherited from binary_function.

struct RangeByA : public std::binary_function<Thing, MultiValuedComparator>
{
   bool operator()(const Thing &left, const MultiValuedComparator &right)
   {
      return left.a == right.a && left.b == right.b;
   }
}

I don't know how to write the equal_range function so it does this. I tried:

void somefunction()
{
   typedef pair<vector<Thing>::iterator, 
                vector<Thing>::iterator> startEndIterPair;

   MultiValuedComparator mvc(1, 2);

   startEndIterPair p = equal_range
      (
      Things.start(), 
      Things.end(), 
      std::bind2nd(RangeByA, mvc)
      );
}

but this code complains of no match for 'operator<' in '__middle.__gnu_cxx::__normal_iterator .. etc at the call to equal_range

How do I write this so equal_range will work? I have no idea where to place the overloaded operator. RangeByA does not seem to accept it.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

太阳男子 2024-08-30 01:41:01

equal_range 比较器的要求是严格的弱排序(而不是相等)。此外,比较器必须能够使用两种顺序的参数进行调用:

comparator(*iter, value); // items less than lower bound
comparator(value, *iter); // items greater than upper bound

equal_range 的结果就是这两个调用都返回 false 的迭代器范围。

那么,一个简单的调整就是向您的 MultiValuedComparator 添加一个接受 Thing 的构造函数,允许将 Thing 对象转换为 MultiValuedComparator 对象以进行比较:

class MultiValuedComparator
{
public:
   item a;
   item b;

   MultiValuedComparator(item c, item d)
   {
      a = c;
      b = d;
   }

   MultiValuedComparator(const Thing &thing)
   {
      a = thing.a
      b = thing.b
   }
};

然后调整您的比较器以仅使用 MultiValuedComparator 并使用严格的弱排序:

struct RangeByA : public std::binary_function<MultiValuedComparator, MultiValuedComparator>
{
   bool operator()(const MultiValuedComparator &left, const MultiValuedComparator &right)
   {
      // Sorted by a first, then b if necessary
      return (left.a < right.a)
              || (!(right.a < left.a) && (left.b < right.b)));
   }
};

上述方法的另一种替代方案可以避免复制(从 Thing 到 MultiValuedComparator),即简单地在两个方向(Thing 与 MultiValuedComparator 以及 MultiValuedComparator 与 Thing)实现 operator(),从而放弃继承std::binary_function (此处不需要):

struct RangeByA
{
   bool operator()(const Thing &left, const MultiValuedComparator &right) {
      // ... (same body as above)
   }

   bool operator()(const MultiValuedComparator &left, const Thing &right) {
      // ... (same body as above)
   }
};

The requirement of a comparator for equal_range is a strict weak ordering (not equality). In addition, the comparator must be able to be called with the arguments in both orders:

comparator(*iter, value); // items less than lower bound
comparator(value, *iter); // items greater than upper bound

The result of equal_range, then, is the range of iterators where both of these calls return false.

A simple adjustment, then, is to add a constructor to your MultiValuedComparator that accepts a Thing, allowing a Thing object to be converted to a MultiValuedComparator object for comparison:

class MultiValuedComparator
{
public:
   item a;
   item b;

   MultiValuedComparator(item c, item d)
   {
      a = c;
      b = d;
   }

   MultiValuedComparator(const Thing &thing)
   {
      a = thing.a
      b = thing.b
   }
};

And then adjust your comparator to only use MultiValuedComparator and to use a strict weak ordering:

struct RangeByA : public std::binary_function<MultiValuedComparator, MultiValuedComparator>
{
   bool operator()(const MultiValuedComparator &left, const MultiValuedComparator &right)
   {
      // Sorted by a first, then b if necessary
      return (left.a < right.a)
              || (!(right.a < left.a) && (left.b < right.b)));
   }
};

An alternative to the above, which will avoid copies (from Thing to MultiValuedComparator), is to simply implement operator() in both directions (Thing vs. MultiValuedComparator and MultiValuedComparator vs. Thing), dropping the inheritance of std::binary_function (not needed here):

struct RangeByA
{
   bool operator()(const Thing &left, const MultiValuedComparator &right) {
      // ... (same body as above)
   }

   bool operator()(const MultiValuedComparator &left, const Thing &right) {
      // ... (same body as above)
   }
};
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文