用于排序std :: set的C ++ 11 std :: function和std :: reference包装器

时间:2013-02-15 10:58:00

标签: c++ c++11 std functor std-function

我有一个C ++类,其中一个字段是std ::对象集。我想编写自己的比较函数,或者让用户指定一个。在C ++ 11中,有一种处理泛型函数类型的新方法:std :: function。它适用于函数指针,成员函数指针,lambda函数等。

我尝试编写一个简单的实验程序,但它始终保持着工作,即使我做了C ++ 11维基百科的文章所做的事情。也许我只是不知道应该如何使用std :: function和std :: ref。

无论如何,重点是当我从一个简单的lambda函数创建一个std :: function并使它成为一个类成员时,该类的sizeof增长了22.当我从指针创建一个std :: function时一个全局函数,这个std :: function的sizeof是32.所以大小很大。我将使用相同的比较函数来拥有许多对象,所以我更喜欢让所有对象使用它们。

我有两个想法,告诉我你的想法。一个想法,使用std :: ref来存储对函数的引用,这样我就可以定义一个函数,并且许多对象将使用它来比较std :: set元素。第二个想法:如果不能那样工作,或者结果函数对象太大了,也许我可以使用shared_ptr。

您可能想知道:为什么没有一个静态std :: function成员?答案:因为那时所有对象都将使用相同的比较函数。我希望能够拥有1000个对象,其中400个使用一个比较功能,600个使用不同的比较功能。

示例:

class MyClass
{
public:
private:
     std::function<bool (int, int)> compare;
     std::set<int> set;
};

现在我如何让std :: set使用std :: function,并让许多MyClass对象使用相同的函数?

我希望能够在运行时更改比较功能,以便用户能够选择集合中对象的顺序(由GUI显示)。

2 个答案:

答案 0 :(得分:2)

表示共享所有权的标准方法是使用std::shared_ptr。这会增加一些开销,迫使你在堆上分配std::function,但是shared_ptr小于std::function并且它将正确地管理它的生命周期,所以当任何对象仍然存在时使用函数对象它将保持活动状态,并在不再需要时自动销毁。

正如您所建议的,引用共享函数的reference_wrapper可以用作set的比较对象,因为如果reference_wrapper包含可调用类型,则class MyClass { typedef std::function<bool (int, int)> func_type; public: MyClass(std::shared_ptr<func_type> const& f) : compare(f), set( std::ref(*f) ) { } private: std::shared_ptr<func_type> compare; std::set<int, std::reference_wrapper<func_type>> set; }; 是可调用的。 / p>

reference_wrapper

std::set不能为空(如引用),因此您必须使用有效的reference_wrapper对象构造std::reference_wrapper

由于std::set中的std::function只包含一个指向shared_ptr的非拥有指针,因此您需要小心更新集合的比较对象,同时更新shared_ptr,或者你可以删除函数的最后一个引用,因此void MyClass::replace_cmp(std::shared_ptr<func_type> const& f) { set = std::set<int, std::reference_wrapper<func_type>>( std::ref(*f) ); compare = f; } 会破坏它,在集合中留下一个悬空指针。这可以这样做:

{{1}}

答案 1 :(得分:2)

您告诉该套装在constructor initializer list中使用您的比较功能:

class MyClass
{
public:
    template<typename Fc>
    MyClass(Fc compare_func)
        : compare(compare_func),  // Initialize the comparison function
          set(compare)            // Tell the set to use out function for comparison
        {}
};