How to pass reference to function with lambda - c++

I have a data member that is of type:
std::function<T(T&, T&)>&
The constructor accepts an argument of the same type.
How should I send such a function using lambdas?
I've tried
MyClass tmp([](Foo &a, Foo &b) { return a+b; }, ...);
But it fails.
For example:
main.cpp
#include "MyClass.h"
int main()
{
MyClass a([](int x, int y) { return x+y;});
return 0;
}
MyClass.h
#pragma once
#include <functional>
class MyClass
{
public:
MyClass(std::function<int(int, int)>&) noexcept;
private:
std::function<int(int, int)>& fun;
};

You are passing a lambda to a std::function &. A lambda is not a std::function so that doesn't work directly. However, a lambda is convertible to a std::function, so a temporary std::function has to be build that holds the lambda.
Since you are taking a std::function & C++ assumes you want to modify that value, otherwise there would be no point in taking it by non-const reference. Modifying a temporary has no effect, so this doesn't make sense, so C++ doesn't allow it.
One way to fix the issue is to take a const std::function &. That way there is no modifying of a temporary.
Another way is to pass an actual std::function that you create in main.
Another way is to create a template that just forwards it's argument to the std::function:
class MyClass
{
public:
template <class T>
MyClass(T &&t)
: fun(std::forward<T>(t)){}
private:
std::function<int(int, int)> fun;
};
That way MyClass takes anything and uses it to construct fun. Note that fun is not a reference anymore. The std::function has to live somewhere and since it is part of MyClass it makes sense to tie the lifetime of the std::function to MyClass.
If you really want fun to be a reference you need to find a place for it and make sure it stays there until after MyClass a; gets destroyed. I do not recommend this route since it gets increasingly difficult to make sure the lifetimes are correct.
You can also store the lambda directly, but that is a bit tricky and depending on what you actually want to do with MyClass it may not be viable.

Related

c++ forward variadac function arguments to a class constructor

In C++, is there a way to define a function that takes N number of random arguments (number and parameter types could be anything) and in that function, instantiates a class who's constructor expects those arguments. In pseudo-code, something like:
class ClassType {
ClassType(int, string){}
};
void func(Args ...) {
ClassType A(Args);
}
And better yet, define a function pointer for "func"
Yes it is possible. Output of this
#include <iostream>
#include <utility>
struct ClassType {
ClassType(int a, std::string b){
std::cout << a << b;
}
};
template <typename...Args>
void func(Args&& ... args) {
ClassType A(std::forward<Args>(args)...);
}
int main() {
func(12,std::string("foo"));
}
is
12foo
However, it isnt quite clear why you want func to be variadic when ClassTypes constructor only accepts int,string. Calling func with any other combination will fail.
And better yet, define a function pointer for "func"
You cannot have a function pointer to a template (you also cannot have a function pointer to a whole set of overloads). Thats not how function pointers work. What you can do is taking a function pointer to one particular instantiation of func:
auto fptr = &func<int,std::string>;
If you need some function like object that you can pass around then you can use a generic lambda instead of a bare function pointer (since C++17 I believe):
auto flamb = [](auto&&...args){ func(std::forward<decltype(args)>(args)...); };
This works because the lambda is of some type (albeit unnamed and unspecified) and only its operator() is templated. Hence you can pass such lambda around and only when actually calling it the respective operator() is instantiated. Though, also with that you can only call it with the right parameters (int and std::string).

std::forward and ref-qualifiers for member functions

I was in a position where I was using std::forward wherever I had a forwarding reference and I was wondering if some of that was unnecessary or even wrong. For example having std::forward in a std::begin() call.
Because of the ability of a class being able to overload its member functions based on whether the call is made with the object as an rvalue or not https://akrzemi1.wordpress.com/2014/06/02/ref-qualifiers/, I assumed that a templated function would be as efficient as possible if you were knew that the inner function you were forwarding the object to was non-mutating and/or was a member function of the object. For example
template <typename Something>
void do_something(Something&& something) {
std::forward<Something>(something).do_something();
auto iter = std::begin(std::forward<Something>(something));
for_each(iter, std::end(std::forward<Something>(something), []() {});
}
I saw this question (When not to use std::forward with r-values?) but it did not address the member function ref-qualifiers and it also did not clearly address what the best practice is when you don't have access to the inner functions definitions that you are calling.
Is there a general guideline for when not to use std::forward that addresses the things I mentioned? Or is there some key concept that I am missing?
Except if you know the type you will have, avoid to use std::forward several time in the same function for the same object, as the second time, your object might be moved.
// assuming implementation which really need pass by value instead of const reference
template <typename T> void pass_by_value(T t) { std::cout << t; }
template <typename T>
void foo(T&& t)
{
pass_by_value(std::forward<T>(t));
pass_by_value(std::forward<T>(t));
}
a call of foo with std::string
foo(std::string("Hello world")); // or "Hello world"s
might call the equivalent to
pass_by_value(std::string("Hello world"));
pass_by_value(std::string("")); // Moved string...
The problem is a use after object moved from ("stealed"). If something used in a multiple lines of do_something, then use std::forward only at the last such line to prevent the problem.

does passing lambda by value or reference make it easier to inline?

A similar question has been asked before, but I'm still confused. The STL, I believe, exclusively passes by value, as passing by reference might have consequences in a multi-threaded environment. Say, when two or more threads are executing a mutable lambda. I currently use a universal reference when I just want to invoke a lambda:
template <typename F>
inline void invoke(F&& f)
{
f();
}
This binds to any function object, just like a const& would, but maybe it's a bad idea for inlining. Is a lambda passed by copy easier to inline by the compiler? I'd like the passed lambdas to be as "inlinable" as possible.
Think of a lambda as a small object with a function call operator:
int foo = 1000;
auto f = [=]() ->int { return foo; };
is somewhat equivalent to:
class FooLambda {
int foo;
public:
FooLambda(int foo) : foo(foo) {}
int operator()(){ return foo; }
};
// ...
int foo = 1000;
FooLambda f(foo);
So you see, the function body itself can be inlined if it is seen in the same translation unit as it is called (and possibly if not by some smarter compilers). Since your invoke is a template, it knows the actual type of the lamdba, and you don't force it to jump through function-pointer hoops, which a big inhibitor of inlining.
Taking the callable object by value or reference in invoke determines whether the captured variables are local to the function body or not, which can make a difference if it means they will be in cache.

How does boost::ref work?

Having read couples of explanations here on StackOverflow, I still don't have a clue to how it works and what it is for. The demos I saw all use boost::reference_wrapper<int> as the type, that is, they all wrap int, and they also all run prefix op++ to show how it affects the wrapped int in the function template. One expert said the ref wrapper will be cast into the wrapped object if op++ is called on the ref wrapper, but it seems that it's not how it works. Please see the following example that demonstrates what would happen if the wrapped object is not an int. You may want to compile it before reading the code, so as to save your precious time.
// Build int version: g++ thisFile.cpp -Wall
// Build CFoo version: g++ -std=c++11 thisFile.cpp -DDONT_USE_INT -Wall
#include <boost/ref.hpp>
#include <iostream>
using namespace boost;
using namespace std;
class CFoo
{
public:
CFoo(int val) : m_val(val) {}
CFoo& operator++(void) {
++m_val;
return *this;
}
private:
int m_val;
friend ostream & operator<<(ostream& ostrm, const CFoo& param);
};
template <typename T>
void a_func_tmpl(T param)
{
++param;
}
ostream & operator<<(ostream& ostrm, const CFoo& param)
{
ostrm << param.m_val;
return ostrm;
}
int main(int argc, char *argv[])
{
#if defined(DONT_USE_INT)
CFoo obj(0);
#else
int obj(0);
#endif
a_func_tmpl(obj);
cout << obj << endl;
a_func_tmpl(ref(obj));
cout << obj << endl;
return 0;
}
Below is the output of compiling.
$ g++ -std=c++11 thisFile.cpp -Wall
$ ./a.out
0
1
$ g++ -std=c++11 thisFile.cpp -DDONT_USE_INT -Wall
thisFile.cpp: In instantiation of ‘void a_func_tmpl(T) [with T = boost::reference_wrapper<CFoo>]’:
thisFile.cpp:40:22: required from here
thisFile.cpp:22:2: error: no match for ‘operator++’ (operand type is ‘boost::reference_wrapper<CFoo>’)
++param;
^
As you can see, it does work if the wrapped type is int, but a compile-time error happens if the type is not int even if the wrapped type offers op++. It would be highly appreciated (I've been stuck on this for 2 days T_T) if someone can explain what really happens when a method of wrapped type is called on the wrapped ref. Thanks in advance. m(_ _)m
reference_wrapper is really simple, the easiest way to understand how it works is simply to look at the code. The generator functions, ref and cref that create a reference_wrapper are even simpler, again, just look at their definitions.
Understanding what it's for is also pretty simple: the intended use of reference_wrapper is to pass a variable by reference through a generic API that usually takes arguments by value. That's it.
That's useful when you have wrapped some function or functor in a forwarding API, and want to ensure the forwarding API passes references not values.
For instance, boost::bind copies its arguments into the callable object that it returns, and then invokes the target function passing the copied objects as arguments.
e.g. when you call boost::bind(&func, i) it returns a functor that contains a copy of &func and a copy of i. When you invoke that functor, it calls func with the copy of i. So if the function takes a reference, that reference is bound to the internal copy of i not to i itself. So if you have:
void func(int& i) { ++i; }
int i = 0;
auto bound = boost::bind(&func, i);
bound();
assert( i == 1 ); // FAILS!
The assertion will fail, because the int that gets passed to func is not i but a copy of i stored inside bound.
If you actually want the bound function to be called with a reference, you need something that is copyable like a value but implements reference semantics, which is where reference_wrapper comes in:
void func(int& i) { ++i; }
int i = 0;
auto bound = boost::bind(&func, boost::ref(i));
bound();
assert( i == 1 ); // passes
Now ref(i) creates a reference_wrapper<int> that refers to i and so bound contains a copy of that reference_wrapper<int>, also referring to i. When you invoke bound it passes the reference_wrapper<int> to func, which triggers the implicit conversion to int&, so that the reference binds to i, and i gets incremented as desired.
Other examples where you would use reference_wrapper are std::thread and std::async (and the Boost equivalents). They copy their arguments and then pass them to the wrapped target functor as rvalues, so if the functor has lvalue reference parameters then you must use reference_wrapper for the code to even compile.
Using reference_wrapper with your a_func_tmpl example doesn't really match the intended use, because the function doesn't take a reference, and you're not calling it through a generic API that would decay references to value anyway. Personally I wouldn't worry too much about why your example works in one case and not in the other, because it isn't the intended use case for reference_wrapper anyway. It's more important to understand what it is meant for, so you can use it in the appropriate places when necessary.
Your usage and understanding of reference_wrapper<> seems to actually be correct. However, you stumbled over another problem, which obscures that.
The problem is that there is no implicit conversion from reference_wrapper<CFoo> to CFoo& for the implicit this parameter. In this case, this would be needed to find operator++. However, it should work fine with a free-standing function that does the same:
void bar(CFoo& foo)
{
++foo;
}
template <typename T>
void a_func_tmpl(T param)
{
bar(param); // This allows the implicit conversion
}
Alternatively, you can implement operator++ as a free-standing function:
class CFoo
{
public:
CFoo (int val) : m_val (val) {}
private:
int m_val;
friend ostream & operator<<(ostream& ostrm, const CFoo& param);
friend CFoo& operator++(CFoo& foo);
};
CFoo& operator++(CFoo& foo) {
++foo.m_val;
return foo;
}
The only problem really is that the compiler doesn't know that it needs to convert from reference_wrapper<CFoo> to CFoo& to find operator++ if you define it in the class. The conversion is available, but it isn't asked for.
The code fails because ++param is calling boost::reference_wrapper<CFoo>::operator++ (because that's what you passed) for which there is no definition.
The interface of reference_wrapper<T> has a conversion operator to T&, but the compiler does not have a way to deduce that that's what you meant. x++ means 'call x::operator++', not 'find any old version of operator++ that I can coerce x into'
try
++(static_cast<T&>(param))
or
T& p = param;
++p;

std::bind and std::function overlap or complementary?

I was looking at this exemple here, combining std::bind and std::function so as to create a command: really neat! The code for the command class goes like this:
class Command
{
private:
std::function<void ()> _f;
public:
command() {}
command(std::function<void ()> f) : _f(f) {}
template <typename T> void setFunction (T t) {_f = t ;}
void execute()
{
if(!_f.empty())
_f();
}
};
Assuming I have a class MyClass containing a member function:
class MyClass
{
public:
void myMemberFn() {}
}
Then the calling code looks like:
MyClass myClass;
command(std::bind(&MyClass::myMemberFn, myClass));
Though I must admit I do not really understand why std::function is needed in addition to std::bind. It seems to me that bind already encapsulates the function call, so why is function needed in Command? Couldn't Commandstore a std::bind rather than a std::function?
I have been looking at documentation for both std::bind and std::function and did not get it...
Anyone has an idea of why std::functionis needed?
PS: I am assuming std::bind ~= boost::bind and std::function ~= boost::function
You have to store the result of the std::bind expression somewhere. The return type of std::bind itself is unspecified by the standard, so you cannot create a named member variable of that type (you can use the C++11 auto to create such a local variable, though!)
Also, any function taking std::function can (due to std::function implicit conversions) accept all sorts of callable objects, not just std::bind results - you can pass it a regular function pointer, a lambda, a custom function object, whatever that can be invoked.
From the bind documnentation,
A function object of unspecified type T, for which std::is_bind_expression<T>::value == true,
and which can be stored in std::function.
So
std::function<void ()> _f;
is needed to store the return value of
command(std::bind(&MyClass::myMemberFn, myClass));
so that this can be actually invoked later.