【问题标题】:Initializing multiset with custom comparison function in C++在 C++ 中使用自定义比较函数初始化多重集
【发布时间】:2013-09-14 03:09:01
【问题描述】:

考虑以下比较函数:

bool compare(std::shared_ptr<myObject> &lhs, std::shared_ptr<myObject> &rhs){
   return lhs->value < rhs->value;
}

现在的想法是初始化一个std::shared_ptr&lt;myObject&gt; 类型的多重集,它使用上述函数对元素进行排序。所以从我读到的书应该是这样的:

std::multiset<std::shared_ptr<myObject>, decltype(compare)*> myset{compare};

问题:

我的问题是,在声明中,我理解传递了一个函数指针来引用比较函数,但为什么我们要使用 {compare} 初始化集合?它的重要性是什么?为什么有必要这样做?

【问题讨论】:

    标签: c++ decltype multiset


    【解决方案1】:

    因为集合需要一个比较函子才能使用。如果您不指定一个,它将生成一个默认构造的。在这种情况下,由于您使用的是函数指针类型,因此默认构造的将是一个空指针,它不能被调用;因此,您必须在运行时提供正确的函数指针。

    更好的方法可能是使用函数类类型(又名函子类型);那么函数调用可以在编译时解决,默认构造的对象会做正确的事情:

    struct compare {
        bool operator()(std::shared_ptr<myObject> &lhs, 
                        std::shared_ptr<myObject> &rhs) const {
            return lhs->value < rhs->value;
        }
    };
    
    std::multiset<std::shared_ptr<myObject>, compare> myset;
    

    【讨论】:

    • 谢谢,在阅读 jrok 评论/答案后,我再次阅读了您的答案并理解了您的观点,之前我不明白(:
    【解决方案2】:
    模板参数中的

    decltype(compare)*指定了比较器的type。它不会告诉 要使用哪个 函数 - 是 comparefoobar 还是别的什么。因此构造函数参数。

    【讨论】:

    • ins't decltype(compare) 指的是类型,当我们添加 (*) 时,整个表达式指的是函数指针????
    • 参数是一个类型 - 在你的情况下它与bool(*)(shared_ptr&lt;myObject&gt;&amp;, shared_ptr&lt;myObject&gt;&amp;) 相同。这并不能说明它是哪个函数。
    • 好吧,这是有道理的,但我仍然对为什么需要将实际函数放在初始化块中感到困惑,对我来说这只是复杂的语法,或者我可能还需要研究模板?
    • @Jason decltype 在编译时查询表达式的类型,而函数指针本身是运行时存在的对象。也许您确实需要研究模板 - 查找类型和非类型模板参数之间的区别。
    【解决方案3】:

    为了访问您的元素,您需要为您的类型提供strict weak ordering 的函数。

    std::multiset 有以下构造函数:

     explicit multiset (const key_compare& comp = key_compare(),
                   const allocator_type& alloc = allocator_type());
    

    如您所见,您可以通过将comp 函数指针(或函数对象)传递给构造函数来实现。


    【讨论】:

      【解决方案4】:

      传递给模板的比较器必须是可以用函数调用运算符调用的东西的类型。那可能是一个重载了该运算符的类,或者是 lambda 或函数指针的类型。在 set 的 cunstrutor 中,必须传递该类型的实例。所以decltype(compare)*是函数指针类型,&amp;compare是函数指针。

      【讨论】:

      • 但是如果我们严格来说总是调用同一个函数并引用它的类型,为什么我们需要单独指定这些呢?难道我可以参考类型并调用不同的函数/lamda等
      • 不同的 lambda:不,因为另一个 lambda 将有另一种类型。不同的功能:是的,如果它具有相同的类型。这意味着,您可以有两组相同类型,但比较器的工作方式不同,例如与lhs-&gt;value &gt; rhs-&gt;value。类型必须单独指定,因为这是模板的工作方式——在函数中,模板参数可以推导出来,但std::set 是一个类,所以它不可能在那里。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-09-20
      • 1970-01-01
      • 1970-01-01
      • 2022-12-16
      • 1970-01-01
      • 2021-12-21
      • 1970-01-01
      相关资源
      最近更新 更多