std::function template syntax - c++11

I am fimilar with std::function , but i am reading a book that there is a code like this :
template<typename GameObject, typename Function>
std::function<void(SceneNode&, sf::Time)> derivedAction(Function fn)
{
return [=](SceneNode& node, sf::Time dt)
{
assert(dynamic_cast<GameObject *>(&node) != nullptr);
fn(static_cast<GameObject *>(&node), dt)
}
}
then the book use template like this :
Command moveLeft;//command is a structure
moveLeft.action//action is a std::function object
= derivedAction<Aircraft>(AircraftMover(-playerSpeed, 0));
//derivedAction specify<Aircraft> ???
my questions are :
1-derivedAction must be an object of std::function , i have checked references but i haven't found this kind of initialazation with {} , how this works ?
2-it is complicated to me , to understand the lambda expression , and why there is a return for it ?
i am pretty confused about this peice of code , any explination would be appreciated

std::function is a wrapper around anything, that can be called (i.e, you can use operator() on it). That is pointer to a function, class having operator() overloaded or lambda expression.
In your case, derivedAction is a templated function, accepting a single parameter (of templated type of name Function) and returning a function having void return type and accepting two parameters -- SceneNode& and sf::Time.
So to answer your questions.
1-derivedAction must be an object of std::function , i have checked references but i haven't found this kind of initialazation with {} , how this works ?
No, derivedAction is a function itself, like any other (i.e. int foo(){ return 0; }).
2-it is complicated to me , to understand the lambda expression , and why there is a return for it ?
Once again, the return value of derivedAction is a function (or rahter, something, which is callable).
If you look closely to the code of derivedAction, you will see, that it only wraps a function Function fn with some checks.

For your first question, derivedAction is a function, so you could define an empty body {} just like with any other function.
As for your second question, the return is the return of derivedAction. The breakdown of the lambda is as follows:
[=] Instructs to capture any referenced variable by making a copy
(SceneNode& node, sf::Time dt) describes the input arguments of the lambda function
In the body of the lambda, the lambda function operates on fn(). It casts node to a different type and modifies the node object.
In your example, fn is AircraftMover(-playerSpeed, 0). playerSpeed is of type SceneNode&, and 0 is of type sf::Time. The return type of that function is void. So, what all of this does in the end is modify the playerSpeed you feed into it based on dt. Hope this makes sense..!

Related

universal reference as parameter and return type

Universal references as parameter or return type
I read a few articles about universal references but I still don't understand in which cases I might need to use this as a parameter type besides the move constructor. Could someone enlighten me?
void Foo(Bar&& x);
Bar&& Foo();
Under which circumstances would I ever want to have this which I couldn't solve with a simple Bar& to move something?
When to use std::move
Could someone explain me when an explicit std::move is necessary (for parameters and return types) under which circumstances I can expect that the compiler uses it automatically during the optimization phase? For example
struct A { A(A&& src) ... };
A Foo()
{
A a;
...
return a;
}
In this case I might benefit from RVO, so should I even ever consider using std::move for a result? Thanks a lot!
Universal references
The example you've provided doesn't actually use universal references, those are just r-value references. Syntactically, the universal reference is an r-value reference to a parameter of a deduce templated type:
template <typename Bar>
void foo(Bar &&bar);
This is actually different then a regular r-value reference and it is used to solve a perfect forwarding problem. But I assume this isn't what your question is about.
R-value references
In most cases when you want to move the value to or from the function you can simply do it by value:
void foo(Bar b);
...
Bar somebar;
foo(std::move(somebar)); //function argument is move-constructed
/**************************************************************/
Bar foo()
{
Bar somebar;
return somebar; //return value is move-constructed
}
Doing this using l-value reference is actually incorrect:
void foo(Bar &b)
{
Bar somebar = std::move(b); //you "stole" passed value
}
...
Bar somebar;
foo(somebar); //but the caller didn't intend to move his value
Also returning any reference to a local variable is wrong.
The only reason one would use r-value reference instead of passing by value is to allow moving the value without actually moving it one extra time:
Bar &&Foo::foo()
{
return memberBar;
}
...
Foo f;
Bar b = f.foo(); //"b" will be move-constructed
...
f.foo().doBar(); //returned "Bar" value is just used and not moved at all
When to use std::move
You need to use std::move every time you want to move a variable even if it's already an r-value reference:
Foo::Foo(Bar &&bar)
: memberBar(std::move(bar)) //still need to move explicitly!
{
}
You don't need to use std::move when:
Returning a local variable by value
Passing a temporary to a function, e.g. foo(Bar())
Passing non-movable types (those without move-constructor) including primitive types
A common mistake:
Bar *bar = new Bar();
foo(std::move(bar)); //not needed! nothing to move since the pointer is passed and not the object itself
However when using a conditional operator:
Bar foo()
{
Bar somebar;
Bar otherbar;
return std::move(true ? somebar : otherbar); //need to move explicitly!
}

How do I pass static_cast<T> as a function?

I have a type A that's designed to be implicitly casted to type B. Here's an example case I'd like to use it in:
// Current implementation:
std::transform(vec_of_a.begin(), vec_of_a.end(), std::back_inserter(vec_of_b),
[](const A& a) -> B { return a; }); // Thanks, Kerrek SB.
// Ideal implementation - Won't compile, expected '(' after 'static_cast'.
std::transform(vec_of_a.begin(), vec_of_a.end(), std::back_inserter(vec_of_b),
static_cast<B>);
What can I do to make the latter option compile?
static_cast<B>, while it is invoked with function-call syntax cannot be passed like other callable things. E.g., there's no way to use & to get a function pointer to it.
You can use a short little lambda to achieve something similar to passing a function pointer to static_cast<B>, as you do in your current implementation:
std::transform(vec_of_a.begin(), vec_of_a.end(), std::back_inserter(vec_of_b),
[](const A& a) -> B { return a; });
Another option--in this particular case--would be to construct a vector<B> from the vector<A>:
std::vector<B> vec_of_b(vec_of_a.begin(), vec_of_a.end());
(This answer is a summary of the comments on both the question and bipll's answer.)
Build a functor enclosing static_cast:
template <typename T>
struct StaticCast
{
template <typename U>
T operator()(const U& rhs)
{
return static_cast<T>(rhs);
}
};
With this, you can call std::transform:
std::transform(vec_of_a.begin(), vec_of_a.end(), std::back_inserter(vec_of_b), StaticCast<b>());
It can be used in the case the output vector is already defined in place of the lambda shown in comments. If not, prefer the constructor mentioned in another answer**.
This functor version is compliant with C++98 if needed -- even if OP is tagged C++11, it may be worthy to note this point.
** Note that with this particular constructor, a warning C4244 is raised with VS compiler (tested with VS2017).
Yes, that's the way anonymous functions work in C++, and static_cast is not a function so you cannot pass its address as the mapped function. You'll have to deal with it.
You cannot use a constructor either.

What's the difference between lambda and std::function?

In this sample:
auto f = [](int some, int some2){
//do something
};
This case it is a functor or object of function?
std::function<void(int, int)> f = [](int some, int some2) {
//do something
}
Now, in this case, whats is the results? Functor or Object of function?
The first f (i.e., the one designated with auto) results to what is called a lambda function. Also knows as a closure. Closures are unnamed function objects. That's why we need auto to deduce the type of a closure. We don't know it's type but the compiler does. Thus, by using auto we let the compiler deduce the type of the unnamed closure object for us.
The second f (i.e., the one designated with std::function) is a std::function object. Class std::function is a general-purpose polymorphic function wrapper.
Lambdas closures as function objects can be converted to their respective std::function objects. That is exactly what is happening in:
std::function<void(int, int)> f = [](int some, int some2) {
//do something
}
The lambda closure on the right hand side is assigned and converted to the std::function object on the left side of the assignment.
Practically, they're both interpreted as functors, since they both overload call operator() and thus can be called, except for that the lambda's type is unnamed.
Another difference between those two is that you can't assign between lambda closures, since for lambda closures the assignment operator is declared deleted. while you can assign between std::function objects.

Move constructor not getting called? (C++11)

In the following example, why doesn't the move constructor get called in the construction of 'copy' inside fun, even though the 'src' argument of 'fun' is explicitly a rvalue reference and is only used in that construction?
struct Toy {
int data;
Toy(): data(0)
{
log("Constructed");
}
Toy(Toy const& src): data(src.data)
{
log("Copy-constructed");
}
Toy(Toy&& src): data(src.data)
{
log("Move-constructed");
}
};
Toy fun(Toy&& src)
{
Toy copy(src);
copy.data = 777;
return copy;
}
Toy toy(fun(Toy())); // LOG: Constructed Copy-constructed
While Bob && b is an rvalue reference, all named use of data after construction is using it as an lvalue.
So Bob&& b will only bind to rvalues, but when you use it it will not move.
The only ways to get an rvalue reference are:
A value without a name, such as a temporary return value or result of a cast.
Use of a local value variable in a simple return x; statement.
Explicitly casting to an rvalue, such as with std::move or std::forward.
This prevents data from being silently moved from on one line and then used on the next. It can help to think of rvalue as being 'I the programmer say this is not needed after this expression' at use, and 'only take things that are not needed afterwards' in function parameters. The temporary/return exceptions above are two spots the compiler can relatively safely guarantee this itself.
Finally, note that universal references (auto&& and T&&) look like rvalue references but sometimes are not.

C++ functor passing through recursion: "attempt to use a deleted function"

Context
Assessment piece for a data structures and algorithms course, an exercise in using an AVL tree and hash table to parse input to create a dictionary file and then use that file to perform cursory spell checking.
N.B.: I am not asking for help in solving this problem that's not what I'm having difficulty with. I am asking for help understanding an aspect of C++ function object passing/usage that is causing me considerable frustration. This aspect of C++ is not part of the assessment, there are no marks attached to it, I simply have a personal issue submitting code I dislike the design of.
Problem
Passing a functor to a recursive function results in compiler error, "attempt to use a deleted function." I thought this was an issue with passing the functor by value, so I changed the parameter to pass by reference which yields a, "no matching member function for call to <public member function of AVL tree that kicks off the recursion>," in which case I don't know how to alter the function declaration so it does match. I have also tried making the parameter: const UnaryFunction& action (a constant function-object reference), but this yields the compiler error, "no matching function for call to object of type 'const std::__1::__mem_fn<void (DictGen::*)(std::__1::basic_string<char> &)>'," in which case I can't understand why it wouldn't be matching to the DictGen::output signature.
Code
Relevant parts of AVL tree class:
template <class T>
struct AVLNode
{ // simple data carrier node for AVL tree
AVLNode<T>* lChild;
AVLNode<T>* rChild;
AVLBalance balFac;
T data;
};
template <class T>
class AVLTree<T>
{
...
AVLNode<T>* root;
template <class UnaryFunction>
void inorderAction( AVLNode<T>* node, UnaryFunction action )
{
if ( node != NULL )
{
inorderAction( node->lChild, action );
action( node->data ); // << problem line
inorderAction( node->rChild, action );
}
}
public:
template <class UnaryFunction>
void inorder( UnaryFunction action )
{
inorderAction( root, action );
}
}
Relevant parts of DictGen class:
class DictGen
{
...
FILE* outStream;
AVLTree<std::string> dict;
void output( std::string& word )
{
fprintf( outstream, "%s\n", word.c_str() );
}
public:
goGoGadgetDictionaryGenerator()
{
...
dict.inorder( std::mem_fn( &DictGen::output ) ); // << also problem line
}
}
Interpretation/Translation
AVL tree class has a flexible inorder traversal that allows me to action the node however I want with the given UnaryFunction action. A DictGen object is initialised with a FILE* so DictGen instances may output to different files, hence the need to pass a member function object in the dict.inorder( ... ) call.
Efforts/research so far
My initial solution was to follow the functions as parameters example given in our textbook which involved using C function pointers and polluting global space. Although this worked I was unsatisfied with this design; I wished to bundle this behaviour in a DictGen class.
My after consulting both my lecturer and lab tutor they suggested using C++ functors but weren't able to help with implementation as neither had used functors in a while.
I forged ahead finding very handy material on SO (helping me reference a member function), several functor tutorials via Google and an excellent PDF from a Stanford course regarding functor implementation and usage. However, while all these resources have carried me this far, none have been able to shed any light on my current predicament. I was really hoping making the parameter a const UnaryFunction& would solve it but can't understand why the signature doesn't match.
I have also tried using an inline lambda but require the object context to access outStream.
I have spent the last four days ploughing away at this issue and the only remaining lead I have is an SO post that casually remarked that the C++ spec contains information about the implicit deletion of function objects but I haven't been able to make any further progress. If there is an SO post that solves my issue, I haven't been able to find it.
Questions
Does the recursion really have anything to do with this issue?
Is there some novice aspect of functor passing/usage I'm not grasping?
What is causing the function to be deleted?
What am I missing about getting the function signatures to match when it appears that function deletion isn't the issue?
This is my very first SO post, I have done my best to keep the question-asking suggestions in mind. I welcome any constructive criticism to help me improve this post so that I can it can both solve my issue and serve as a future resource for similar issues.
You need to have an instance of DictGen bound to the member function:
// ...
void gen()
{
dict.inorder(
std::bind( std::mem_fn( &DictGen::output ),
this, std::placeholders::_1) );
}
// ...
You are coding in C++11. While there are uses for std::mem_fn and std::bind, they are a very awkward way to generate these kind of functors.
void gen()
{
dict.inorder(
[this]( std::string& word ) { this->output(word); }
);
}
while the lambda syntax might be somewhat new to you, this is far less backwards than the std::bind( std::mem_fn( &T::method ), this, std::placeholders::_1)
The basic syntax of a lambda is:
[capture-list]( arguments )->return value { code }
where capture-list is [=] (auto-capture by value) or [&] (auto-capture by reference) or [var1, var2] (capture var1 and var2 by value) or [&var1, &var2] (capture var1 and var2 by reference) or a mixture of same. (C++1y adds new syntax, like [x = std::move(y)])
(arguments) are just a usual function argument bit. It is actually optional, but required if you want a return value.
-> return value is optional for single-statement lambdas, or lambdas that return void. (In C++1y, it is optional even with multiple returns)
Then the code.

Resources