7

I have been using Loki's Functor for a while and I recently asked a question about it (still unanswered...) I have been told to use std::function, but I prefer Loki's implementation of Functor since it also work with all sorts of pointers as parameters (e.g. 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);
}

Is there a way to do so with std::function ?

markalex
  • 8,623
  • 2
  • 7
  • 32
Athanase
  • 933
  • 9
  • 25

3 Answers3

6

Use std::bind.

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

here, func will be deduced to type, that was returned from std::bind or if you don't like auto you can use (and you want to use std::function)

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

Here std::function will be constructed from result of std::bind. ptr will be copied to some object returned from std::bind, however you can use std::ref/std::cref if you don't want copies.

ForEveR
  • 55,233
  • 2
  • 119
  • 133
  • 1
    I don't think this works with `shared_ptr`, and if it did, it wouldn't re-evaluate the pointer at each call. Also, note that these one-liners do completely different things: `bind()` does not return a `std::function`. – Potatoswatter Dec 16 '13 at 11:11
  • @Potatoswatter it works with `shared_ptr`. Why it should reevaluate? – ForEveR Dec 16 '13 at 11:17
  • Ah, I missed the subtlety of the INVOKE concept. Indeed it makes a copy and dereferences every time. I was thinking in terms of conversion. Still, please note that `auto` stores a statically-dispatched bind object, not a dynamically-dispatched `std::function`, and those are completely different things. – Potatoswatter Dec 16 '13 at 11:20
  • @Potatoswatter it works like `Loki::Functor`, nothing special. It can do copy, it can not. – ForEveR Dec 16 '13 at 11:22
  • Perfect answer, thanks a lot. It will start using this from now. Still... I would have loved to understand how to make `Loki::Functor` work with variadic templates. Thank you again ! – Athanase Dec 16 '13 at 11:27
  • @Athanase So you want to use `Loki::Functor` to construct a functor and then use it as a `std::function`? Try to simply assign it to `std::function`, it might work. – leemes Dec 16 '13 at 11:29
  • @leemes I wanted to modify the implementation of `Loki::Functor` to make it work with variadic templates because right now there is a lot of uneeded template specialization, and a limited number of arguments. This is just a personnal programming excercise... – Athanase Dec 16 '13 at 11:33
  • @Athanase it's not so simple. But however, if you read more about variadic templates - you can do this. Loki is writed on typelist concept, so, you should rewrite it on concept of variadic templates. – ForEveR Dec 16 '13 at 11:40
2

If you don't want to use std::bind, an option is to use a lambda function, resulting in even smaller code and I personally find it more intuitive:

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

or without auto:

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

But this only works if the function to be called is fixed (i.e. &Toto::foo was not passed dynamically). If not, it's still possible with a lambda but you need a slightly different syntax and std::bind might be more attractive again.

leemes
  • 44,967
  • 21
  • 135
  • 183
1

Use 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 );
}

Live demo.

Edit: The inner bind with a lambda expression is actually unnecessary, but I'll just leave this here as illustrative of more advanced usage.

Potatoswatter
  • 134,909
  • 25
  • 265
  • 421