【问题标题】:std::pair with a comparable and a non-comparable object needs to be sorted需要对具有可比较对象和不可比较对象的 std::pair 进行排序
【发布时间】:2018-06-26 21:44:53
【问题描述】:

我遇到了以下问题。我有一个std::vector< std::pair<int, Move> > x 类型为std::pair<int, Move>,其中Move 是一个没有定义任何比较运算符的任意对象,例如< > !+ == <= >= 等等。

我将Move 对象与整数值配对的主要原因是Move 对象应该有一个数字来描述它们出于某种目的的优先级。主要目的是对向量进行排序,从而使用它们各自的整数值对 Move 对象进行排序。

当我想使用std::sort 函数对向量中的这些对进行排序时,真正的问题就开始了。最初我认为只有std::pair 的第一个元素对比较很重要,然而,结果证明这两个对象都需要为它们定义比较操作才能成功编译程序。

因为我不想修改原来的 Move 类,所以我编写了一个 Wrapper 类,它应该包装 std::pair<int, Move> 并在其上定义一个比较操作,以便可以对 std::vector< Wrapper < std::pair<int, Move> > > x; 进行排序而无需修改Move 类。这里的逻辑是vector 提供了一个定义了< 操作的类。

我使用了下面的包装类:

template <typename T>
struct Wrapper{
    Wrapper(const T & pair): pair_mem(pair)
    bool operator(const T & other_pair) const{
          return this->pair_mem.first < other_pair.first;
    }
    T pair_mem;
};

好吧,您可能已经猜到上面的方法不起作用,我不得不经历一堆编译器错误。最后,我尝试将&lt; operator 添加到 Move 类中,即使之后我也无法编译程序。

以下是我认为最重要的错误。

: note: this candidate was rejected because mismatch in count of arguments
    struct Wraper{
           ^
: note: this candidate was rejected because mismatch in count of arguments
            Wraper(const std::pair<int, Move> & move){

我使用mpiCC作为编译器

更新

我确实将T 更改为Wrapper 作为建议的答案之一,但问题没有解决。这是编译器的截图,

【问题讨论】:

  • 您是否考虑过使用std::map?它可以让你建立一个自动排序的键值关系。
  • 我实际上更感兴趣的是我无法编译它的原因。
  • 你能展示一下你是如何使用包装器来得到那个错误的吗(minimal reproducible example)?看起来this 可能会告诉你你需要什么。
  • std::vector&lt; Wrapper &lt; std::pair&lt;int, Move&gt; &gt; &gt; x; 是编译错误的来源。 Wrapper 是一个定义了比较的类。它需要std::pair&lt;int, Move&gt;
  • 您可以将自己的比较函数传递给std::sort

标签: c++ c++11 templates compiler-errors


【解决方案1】:

你的包装类应该类似于:

template <typename T>
struct Wrapper{
    Wrapper(const T & pair): pair_mem(pair) {}
    bool operator <(const Wrapper& rhs) const {
        return pair_mem.first < rhs.pair_mem.first;
    }
    T pair_mem;
};

Demo

但使用自定义比较器似乎更好(侵入性更小)。

std::sort(x.begin(), x.end(),
          [](const auto& lhs, const auto& rhs) {
              return lhs.first < rhs.first;
          });

【讨论】:

  • 我实际上做了运算符重载操作const但忘记在这里包含它。但没有帮助。
  • @nmd_07 比较参数是Wrapper,而不是T
  • @1201ProgramAlarm 似乎是真正的原因。
  • 您可以使用类似于 Barton-Nackman 的技巧。使用朋友,您可以在全局范围内注入比较运算符。
  • @nmd_07:我刚刚提供了一个Demo link
【解决方案2】:

如果您使用的是最新的 c++ 编译器,则可以使用 lambda:

std::sort(std::begin(x), std::end(x), [](auto & l, auto & r) {return l.first < r.first; });

【讨论】:

    【解决方案3】:

    当编译器吐出错误时,不要跳过第一条消息。从您的图像中(您确实应该复制文本而不是创建图像):

    错误:没有构造函数Wraper&lt;T&gt;::Wraper 的实例与参数列表匹配 vector(size_type __n, const value_type&amp; __value = value_type()

    value_type() 处显示错误(由下一行的插入符号)。您确实输入问题的消息不是错误,而是对编译器试图找到丢失的构造函数的解释。他们列出了为value_type 尝试过的struct 和找到的构造函数,即接受T 参数的构造函数。这不匹配,因为编译器正在寻找默认构造函数(无参数)。

    大概在search-abid_parallel.cpp 的第137 行,您使用指定向量初始大小的构造函数声明了包装类的向量。 (此外,根据错误消息,C++11 之前的版本?)此构造函数需要能够默认构造那些初始元素。当您定义不同的构造函数时,默认构造函数被禁止,因此出现错误。

    一些选项:

    1. 默认初始化向量,如果您想在构建向量时避免重新分配,请调用reserve()

    2. 为您的包装类定义一个默认构造函数。

    3. 不要使用包装类。而是给std::sort(不使用C++20执行策略时的第三个参数)一个比较函数。

    4. 不要使用向量。 std::multimap 将存储您的配对并为您分类。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-02-24
      • 1970-01-01
      • 1970-01-01
      • 2016-01-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多