std::function和shared_ptr

7
我已经使用Loki的Functor有一段时间了,最近我提了一个关于它的问题(至今未得到答复...) 有人告诉我应该使用std::function,但我更喜欢Loki的Functor实现,因为它还可以与各种指针类型作为参数一起使用(例如std::shared_ptr)。
struct Toto
{
    void foo( int param )
    {
        std::cout << "foo: " << param << std::endl;
    }
};

int
main( int argc, const char** argv )
{
    std::shared_ptr<Toto> ptr = std::make_shared<Toto>();

    Loki::Functor<void, LOKI_TYPELIST_1(int)> func( ptr, &Toto::foo );

    func(1);
}

有没有一种方法可以使用std::function来实现这个?
3个回答

6
使用 std::bind
auto func = std::bind(&Toto::foo, ptr, std::placeholders::_1);

在这里, func 将会被推导为从 std::bind 返回的类型,或者如果您不喜欢使用 auto,并且想要使用 std::function 的话,也可以使用它。

std::function<void(int)> func = std::bind(&Toto::foo, 
ptr, std::placeholders::_1);

在这里,将从std::bind的结果中构造std::functionptr将被复制到从std::bind返回的某个对象中,但是如果您不想复制,可以使用std::ref/std::cref

1
我认为这不适用于shared_ptr,即使它适用,也不会在每次调用时重新评估指针。此外,请注意这些一行代码执行完全不同的操作:bind()不会返回一个std::function - Potatoswatter
@Potatoswatter 它可以与 shared_ptr 一起使用。为什么它应该重新评估? - ForEveR
啊,我错过了 INVOKE 概念的微妙之处。它确实会每次复制和取消引用。我一直在考虑转换方面。但请注意,auto 存储的是静态分派绑定对象,而不是动态分派的 std::function,它们是完全不同的东西。 - Potatoswatter
非常完美的答案,非常感谢。我将从现在开始使用它。不过...我仍然很想知道如何让Loki::Functor与可变参数模板一起工作。再次感谢! - Athanase
@Athanase 这并不是那么简单。但是,如果你更多地了解可变参数模板,你就可以做到这一点。Loki是基于类型列表概念编写的,因此,你应该将其重写为可变参数模板的概念。 - ForEveR
显示剩余3条评论

2

如果您不想使用std::bind,另一种选择是使用lambda函数,这样可以使代码更加简洁,并且我个人认为更易于理解:

auto func = [&ptr](int p){ ptr->foo(p); };

或者不使用 auto

std::function<void(int)> func = [&ptr](int p){ ptr->foo(p); };

但是这仅适用于要调用的函数是固定的(即未动态传递&Toto::foo)。如果不是,则可以使用 lambda,但需要稍微不同的语法,或者再次使用 std::bind 可能更具吸引力。

1
使用 std::bind
struct Toto
{
    void foo( int param )
    {
        std::cout << "foo: " << param << std::endl;
    }
};

int main() {
    std::shared_ptr<Toto> ptr = std::make_shared<Toto>();
    std::function< void(int) > func( std::bind( &Toto::foo,
        std::bind( [ptr] () { return ptr.get(); } ),
        std::placeholders::_1
    ) );

    func( 1 );
}

在线演示。

编辑:使用lambda表达式的内部bind实际上是不必要的,但我将其保留在这里,以说明更高级的用法。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接