【问题标题】:Replicate std::function or boost::function?复制 std::function 还是 boost::function?
【发布时间】:2014-06-03 13:43:11
【问题描述】:

如何复制std::functionboost::function

我正在使用 C++03 进行编译,并且我正在积极避免提升

这始于我试图将类方法视为常规函数指针。 I learned 关于 std::functionboost::function 的努力。

【问题讨论】:

  • Boost 函数早在 C++11 之前就已经存在了,而且源代码很容易获得。阅读它将具有教育意义(并且很有帮助)。
  • 考虑到您的限制,您确定需要 std::function 吗?
  • 由于 Boost 的内部依赖关系,这可能是一个痛苦的过程,但应该可以隔离 Boost 所需的部分并将它们与您的代码一起复制。
  • 你不需要安装任何东西,因为相关的 Boost 部分只是标题。使用BCP 提取boost::function 所需的标头。

标签: visual-studio-2008 c++11 boost member-function-pointers c++03


【解决方案1】:

您可以使用如下声明创建一个指向成员函数的 pre C++11 函数指针:

ReturnType (ClassType::*func_ptr)() = &ClassType::function;

并使用带有(instance.*func_ptr)() 的类的一个实例 调用它。例如

struct Foo {
    bool memberFunc() { return true; }
};

int main() {
    typedef bool (Foo::*member_func_t)();      // Typedef member func pointer type.
    member_func_t func_ptr = &Foo::memberFunc; // Declare function pointer.
    Foo foo;                                   // Create foo object.
    (foo.*func_ptr)();                         // Call member func using instance.
}

如果您只需要创建指向成员函数的指针,有一种方法可以重新创建您正在寻找的通用属性 (I read your other question too)。如果你混入非成员函数指针,它将不起作用。

通过使用模板和派生自通用非模板基类的包装类,您可以包装一个指向任何类类型成员的函数的成员函数指针。基类创建一个公共类型,独立于包装函数指针是哪个类的成员。如果您例如,这可能很有用。想要将包装器存储在同一个容器中。

只要函数签名始终相同(在这种情况下,它固定为bool()),此示例就可以工作。

struct func_base {
    virtual ~func_base() {};
    virtual bool operator()() const = 0;
};

template <typename C>
class func_wrapper : public func_base {
public:
    typedef bool (C::*member_func_ptr_t)();
    func_wrapper(member_func_ptr_t func_ptr, C* instance_ptr)
        : m_func_ptr(func_ptr), m_instance_ptr(instance_ptr) {}
    bool operator()() const { return (m_instance_ptr->*m_func_ptr)(); }
private:
    member_func_ptr_t m_func_ptr;
    C* m_instance_ptr;
};

您还可以创建一个辅助函数来创建自动推断成员类型的包装器。

/* This function returns a pointer to dynamically *
 * allocated memory and it is thus the callers    *
 * responsibility to deallocate the memory!!      */
template <typename C>
func_base* make_wrapper(bool (C::*func_ptr)(), C* instance_ptr) {
    return new func_wrapper<C>(func_ptr, instance_ptr);
}

现在您可以使用它,例如像这样:

struct Bar { // Define some other class with member function.
    bool memberFunc() { return false; }
};

int main() {
    Foo foo; // Create object instances.
    Bar bar; // ----------||-----------

    std::deque<func_base*> d; // Deque storing pointers to base class.

    // Push pointer to any member func.
    d.push_back(make_wrapper(&Foo::memberFunc, &foo));
    d.push_back(make_wrapper(&Bar::memberFunc, &bar));

    for (std::deque<func_base*>::iterator it = d.begin(); it != d.end(); ++it) {
        (**it)(); // Call all functions in deque.
    }

    for (std::deque<func_base*>::iterator it = d.begin(); it != d.end(); ++it) {
        delete *it; // REMEMBER to destroy wrappers pointed to!!
    }
}

这将使用 C++03 编译器进行编译。请参阅使用 gcc 4.3.2 编译的 live demo

注意:如果需要,您可以轻松地修改包装类以存储实例的副本。

【讨论】:

  • 你太棒了;漂亮的代码。我希望这比它早 2 小时发布。我尝试了很多方法来让它工作,很明显我重写设计会更快。 :( 不过我下次有这个。非常感谢你!
  • @JoshC 很高兴我能帮上忙 :)
【解决方案2】:

你应该可以使用TR1的函数和绑定头文件了:

#include <tr1/functional>
#include <string>
#include <sstream>

struct AddX {
    template <typename> struct  result { typedef std::string type; };

    std::string operator()(int a, int b) const { 
        std::ostringstream oss;
        oss << (a + b);
        return oss.str();
    }
};

int main() {
    using namespace std::tr1;

    function<std::string(int)> foo = bind(AddX(), 999, placeholders::_1);

    return foo(1).length();
}

【讨论】:

  • 找不到这个标题
  • @JoshC 嗯。在这种情况下,以此为灵感(我对签名进行了硬编码,主要是因为没有可变参数意味着一般情况下会有很多繁文缛节的代码):coliru.stacked-crooked.com/a/ff95cf20dcbdf8a9
猜你喜欢
  • 2012-06-25
  • 1970-01-01
  • 2013-02-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多