【问题标题】:priority_queue with custom comparator as value in map constructor error使用自定义比较器作为映射构造函数中的值的 priority_queue 错误
【发布时间】:2021-10-10 16:11:30
【问题描述】:

我创建了一个带有自定义比较器的priority_queue,它以字典顺序存储字符串,它按预期工作。[参考。 this]]

现在,我希望它在unordered_map 中具有价值,我得到了error: no matching constructor for initialization ...,我找到的最接近的是this。我意识到我也需要将比较器传递给构造函数,但是如何?

这是我现在的代码:

#include <iostream>
#include <vector>
#include <unordered_map>
#include <queue>
using namespace std; // Used to make code less verbose


int main() {
  auto cmp = [](string s1, string s2){
        return s1.compare(s2) > 0;
      };

  using myQuque = priority_queue<string, vector<string>, decltype(cmp)> ;
  // This code works
  myQuque pq(cmp);
  pq.push("ZZ");
  pq.push("AA");
  pq.push("CC");
  while(!pq.empty()){
    cout << pq.top() << " ";
    pq.pop();
  }

  // This doesn't. How do I pass 'cmp' to constructor?
  unordered_map<string, myQuque> table;
  auto p = table["r"];
  p.push("ZZ");
  p.push("AA");

}

https://godbolt.org/z/cvPfPd

然后我意识到我也可以在这个应用程序中使用 multiset,但我仍然想知道如何在 map 中使用带有自定义比较器的 priority_queue

【问题讨论】:

    标签: c++ stl


    【解决方案1】:

    问题是使用自定义运行时比较器,myQuque 的默认构造函数不可用。

    std::unordered_map::operator[] 必须能够为值使用默认构造,以防没有为特定键准备好的值。这是必需的,因为它返回对可在赋值表达式中使用的值的引用。

    要修复它你必须删除operator[],你可以使用这个:

      unordered_map<string, myQuque> table;
      auto &p = table.emplace("r", cmp).first->second;
      p.push("ZZ");
      p.push("AA");
    

    演示:https://godbolt.org/z/bPnrEe

    作为替代方案,您可以向priority_queue 提供静态比较器作为 Tony Delroys 的回答。在这种情况下,myQuque 将具有默认构造函数并且问题消失。

    【讨论】:

      【解决方案2】:

      使用 lambda 是个坏主意...只需通过比较模板参数提供比较,然后不需要构造函数参数...

      #include <iostream>
      #include <vector>
      #include <unordered_map>
      #include <queue>
      using namespace std; // Used to make code less verbose
      
      struct Cmp {
          bool operator()(const string& s1, const string& s2) const {
              return s1.compare(s2) > 0;
          }
      };
      
      int main() {
        using myQuque = priority_queue<string, vector<string>, Cmp>;
        // This code works
        myQuque pq;
        pq.push("ZZ");
        pq.push("AA");
        pq.push("CC");
        while(!pq.empty()){
          cout << pq.top() << " ";
          pq.pop();
        }
      
        // This doesn't. How do I pass 'cmp' to constructor?
        unordered_map<string, myQuque> table;
        auto p = table["r"];
        p.push("ZZ");
        p.push("AA");
      }
      

      请注意,我已将比较更改为通过 const 引用获取参数,避免深度复制每次比较所比较的文本(至少只要比您的 std::string 实现可能具有的任何短字符串优化缓冲区长)。

      【讨论】:

        【解决方案3】:

        地图在创建新元素时使用默认构造函数。您可以使用指针,但您需要分配每个新条目:

         unordered_map<string, shared_ptr<myQuque>> table;
         auto p = make_shared<myQueue>(cmp);
         table["r"] = p;
         p->push("ZZ");
         p->push("AA");
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-11-04
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多