Jump to content

  • Log In with Google      Sign In   
  • Create Account

We're offering banner ads on our site from just $5!

1. Details HERE. 2. GDNet+ Subscriptions HERE. 3. Ad upload HERE.


Purpose of std::function


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
6 replies to this topic

#1 larspensjo   Members   -  Reputation: 1557

Like
1Likes
Like

Posted 15 November 2012 - 12:44 AM

What is the purpose of this class template?

I suppose it simplifies the syntax for function pointers. But does it give you anything else but syntactic sugaring?
Current project: Ephenation.
Sharing OpenGL experiences: http://ephenationopengl.blogspot.com/

Sponsor:

#2 Cornstalks   Crossbones+   -  Reputation: 6991

Like
5Likes
Like

Posted 15 November 2012 - 01:14 AM

Sure. Try this with just function pointers (taken from Wikipedia):
std::function<int (int, int)> func; // Wrapper creation using
                                    // template class 'function'.
std::plus<int> add; // 'plus' is declared as 'template<class T> T plus( T, T ) ;'
                    // then 'add' is type 'int add( int x, int y )'.
func = add;  // OK - Parameters and return types are the same.

int a = func (1, 2); // NOTE: if the wrapper 'func' does not refer to any function,
                     // the exception 'std::bad_function_call' is thrown.

std::function<bool (short, short)> func2 ;
if (!func2) { // True because 'func2' has not yet been assigned a function.
    bool adjacent(long x, long y);
    func2 = &adjacent; // OK - Parameters and return types are convertible.

    struct Test {
        bool operator()(short x, short y);
    };
    Test car;
    func = std::ref(car); // 'std::ref' is a template function that returns the wrapper
                          // of member function 'operator()' of struct 'car'.
}
func = func2; // OK - Parameters and return types are convertible.

The particularly nice tidbit (for me) is being able to use functions and functors without changing func's definition/type.
[ I was ninja'd 71 times before I stopped counting a long time ago ] [ f.k.a. MikeTacular ] [ My Blog ] [ SWFer: Gaplessly looped MP3s in your Flash games ]

#3 Álvaro   Crossbones+   -  Reputation: 13880

Like
3Likes
Like

Posted 15 November 2012 - 02:04 AM

Constalks is right. If you need to pass a callback to a piece of code, make sure it accepts an std::function, and then you can use it with function pointers or with functors of any type. This is particularly useful if you want the pass a member function of a particular object as a callback.

Edited by Álvaro, 15 November 2012 - 02:05 AM.


#4 Krohm   Crossbones+   -  Reputation: 3245

Like
1Likes
Like

Posted 15 November 2012 - 03:15 AM

I think it's worth noticing std::function is correctly mapped even when capture lists are used with lambdas.
Function pointers cannot as far as I recall , and sure interfaces cannot.
So they're really the only "complete" way to deal with lambdas, a thing which I consider to be a bit ugly, but that's it.

#5 larspensjo   Members   -  Reputation: 1557

Like
0Likes
Like

Posted 15 November 2012 - 07:33 AM

Thanks for the answers. There is a case I am specifically interested in, but I couldn't find out if it is now possible. I want to use closures with callbacks. Take this example, with a tree walker and a callback for every node in the tree:
class Tree {
	 Walk(void (*callback)(Node*));
};
It is common to also have an extra argument of the type "void *" that will be forwarded to the callback function. I think this is a typical case that a closure would be used, is it now possible?

Something like:
void Callback1(Node*, int);
void Callback2(Node*, int, float);

Tree *t;
auto cb1 = std::bind(Callback1, _1, 77);
t->Walk(cb1);
auto cb2 = std::bind(Callback1, _1, 77, 1.0f);
t->Walk(cb2);
If possible, what is the recommended way to implement this?
Current project: Ephenation.
Sharing OpenGL experiences: http://ephenationopengl.blogspot.com/

#6 Brother Bob   Moderators   -  Reputation: 8570

Like
3Likes
Like

Posted 15 November 2012 - 07:55 AM

If you make Tree::Walk take an std::function<void(Node *)>, you can then do t->Walk([](Node *n){Callback1(n, 77);}). The benefit, as stated above, is that you can pass anything that is callable with a Node-pointer and have no return value: a function pointer, a closure and an old-style function object, and your code doesn't have to know or take special action for the different types of callable objects.

Edited by Brother Bob, 15 November 2012 - 07:56 AM.


#7 larspensjo   Members   -  Reputation: 1557

Like
0Likes
Like

Posted 15 November 2012 - 09:20 AM

If you make Tree::Walk take an std::function<void(Node *)>, you can then do t->Walk([](Node *n){Callback1(n, 77);}). The benefit, as stated above, is that you can pass anything that is callable with a Node-pointer and have no return value: a function pointer, a closure and an old-style function object, and your code doesn't have to know or take special action for the different types of callable objects.


I see, it is that simple! This is something I should be able to use to great advantage.
Current project: Ephenation.
Sharing OpenGL experiences: http://ephenationopengl.blogspot.com/




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS