【问题标题】:Retaining functors as variables将函子保留为变量
【发布时间】:2009-01-23 20:00:43
【问题描述】:

我正在开发一个资源管理类,并希望用户为“ReleaseResource”方法提供一个函子,作为资源管理器构造函数的一部分。从那里请求资源时,将提供函子作为我将返回的 shared_ptr 的删除器,以便在不再使用资源时调用适当的方法。

我遇到的问题是,这需要我将仿函数存储在我的班级中,我不完全确定如何做到这一点。通常在使用仿函数时,您可以像这样对函数进行模板化:

template<class MyFunctor> MyMethod(MyFunctor f) {
    f();
}

如果您打算在该函数的范围内使用函子,这很好,但由于模板超出了函数的范围,我不确定您将如何指定适当类型的变量来存储函子供以后使用。

任何人都可以在这里指出正确的方向吗?

【问题讨论】:

    标签: c++ functor


    【解决方案1】:
    template<class MyFunctor> MyMethod(MyFunctor f) {
        boost::function<void()> g = f;
        g();
    }
    

    您传递给boost::function 的类型是函数类型。例如,int(bool, char) 是返回 int 并采用 bool 和 char 的函数的类型。也就是说,如果您想立即构造 shared_ptr,则不需要将函子存储在某处(boost::function 需要 new 运算符,即使对于非常小的函子,它也会使用特殊技巧来仅使用栈分配(小缓冲区优化)):

    template<class MyFunctor> MyMethod(MyFunctor f) {
        boost::shared_ptr<T> ptr(new T, f);
    }
    

    boost::function 是tr1 的一部分,并将成为下一个官方 C++ 标准的一部分。示例:

    struct Manager {
        template<typename Deleter>
        Manager(Deleter d) 
            :deleter(d) {
    
        }
    
        boost::shared_ptr<Resource> allocate() {
            ...
            return boost::shared_ptr<Resource>(resource, deleter);
        }
    
    private:
        boost::function<void(Resource *)> deleter;
    };
    

    【讨论】:

    • 太棒了!这正是我一直在寻找的。非常感谢!
    【解决方案2】:

    有两种方法,都归结为模板类。

    template <MyFunctor>
    class MyClass
    {
       MyFunctor   func;
      public:
        MyClass(MyFunctor f) :func(f)
        { }
    
    
        MyMethod() 
       {
           func();
       }
    }
    

    这需要你知道函子的类型。为了避免这种情况,我们可以使用工厂:

     template<MyFunctor>
     MyClass<MyFunctor>  MakeFunctorClass(MyFunctor f)
     {     
         return MyClass<MyFunctor>(f);       
     }
    

    另外,由于很可能大部分仿函数签名都是相同的,只有一小部分发生变化,我们可以使用它:

    template <MyType>
    class MyClass
    {
       typedef std::binary_function<MyType, MyType, bool>  MyFunctor;
       MyFunctor func;
      public:
    
    
        MyMethod(MyFunctor f) 
       {
           func = f;
           func();
       }
    }
    

    这使得使用更简单:

     bool AreEqual(int, int); 
     MyClass<int> myc;
     myc.MyMethod(AreEqual);
    

    以更复杂的定义为代价(即,我不保证我给出的 binary_function typedef 会起作用)

    【讨论】:

    • 除非这不是'binary_function'的工作方式。 binary_function 是一个类型特征赋予属性,而不是一个接口。它没有应用运算符,因此即使您提供了参数,语句 'func()' 也是无效的。请参阅有关 boost::function 或 tr1::function 的其他答案。
    • 这就是为什么我特别说“我不保证我给出的 binary_function typedef 会起作用”。我很确定它不会,但我知道有一个标准类型可以。
    【解决方案3】:

    不确定这是否有帮助,但请注意 boost::shared_ptr 具有构造函数覆盖,允许用户包含自定义取消分配(和自定义分配器,如果需要)。这可能足以满足您的需求(如果我正确阅读您的用例,它的设计考虑到了这一点)。

    【讨论】:

    • 我已经意识到这一点,并在上面的示例中使用它。我需要知道的是如何存储你传递给它的参数。
    猜你喜欢
    • 1970-01-01
    • 2019-09-21
    • 1970-01-01
    • 2017-08-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-20
    • 1970-01-01
    相关资源
    最近更新 更多