What is the most efficient way to pass a non generic function? - c++

I am learning functional programming in C++. My intention is to pass a non generic function as argument. I know about the template method, however I would like to restrict the function signature as part of the API design. I worked out 4 different methods example on cpp.sh:
// Example program
#include <iostream>
#include <string>
#include <functional>
typedef int(functor_type)(int);
int by_forwarding(functor_type &&x) {
return x(1);
}
int functor_by_value(functor_type x) {
return x(1);
}
int std_func_by_value(std::function<functor_type> x) {
return x(1);
}
int std_func_by_forwarding(std::function<functor_type> &&x) {
return x(1);
}
int main()
{
std::cout << functor_by_value([](int a){return a;}); // works
std::cout << std_func_by_value([](int a){return a;}); // works
std::cout << std_func_by_forwarding(std::move([](int a){return a;})); // works
//std::cout << by_forwarding([](int a){return a;}); // how to move lambda with forwarding ?
}
Is any of the above attempts correct? If not, how do i achieve my goal?

(based on clarification from comments)
Signature can be restricted by using std::is_invocable:
template<typename x_Action> auto
functor_by_value(x_Action && action)
{
static_assert(std::is_invocable_r_v<int, x_Action, int>);
return action(1);
}
online compiler

Other alternative:
template <typename Func>
auto functor_by_value(Func&& f)
-> decltype(std::forward<Func>(f)(1))
{
return std::forward<Func>(f)(1);
}

however I would like to restrict the function signature as part of the API design.
So restrict it:
#include <functional>
#include <type_traits>
#include <iostream>
/// #tparam F is a type which is callable, accepting an int and returning an int
template
<
class F,
std::enable_if_t
<
std::is_convertible_v<F, std::function<int(int)>>
>* = nullptr
>
int myfunc(F &&x) {
return x(1);
}
int main()
{
auto a = myfunc([](int x) { std::cout << x << std::endl; return 1; });
// does not compile
// auto b = myfunc([]() { std::cout << "foo" << std::endl; return 1; });
}

As usual, this depends on how good your compiler is today, and how good it will be in the future.
Currently, compilers are not very good at optimizing std::function. Surprisingly, std::function is a complicated object that sometimes has to allocate memory to maintain stateful lambda functions. It also complicates matters that std::function has to be able to refer to member function, regular functions, and lambdas, and do it in a transparent manner. This transparency has a hefty runtime cost.
So, if you want the fastest possible code, you should be careful with std::function. For that reason the first variant is the fastest (on today's compilers):
int functor_by_value(functor_type x) {
return x(1);
}
It simply passes a pointer to a function.
When stateful lambdas are involved you have only two options. Either pass the lambda as a template argument, or convert to std::function. Hence, if you want the fastest code possible with lambdas (in today's compilers), you'd pass the function as a templated argument.
Since a lambda function may have a big state, passing it around may copy the big state (when copy elision is not possible). GCC will construct the lambda directly on the parameter list (with no copy), but a nested function will invoke a copy constructor for the lambda. To avoid that, either pass it by const reference (in that case it can't be mutable), or by rvalue reference:
template<class Func>
void run2(const Func & f)
{
std::cout << "Running\n";
f();
}
template<class Func>
void run(const Func & f)
{
run2(f);
}
int main()
{
run([s=BigState()]() { std::cout << "apply\n"; });
return 0;
}
Or:
template<class Func>
void run2(Func && f)
{
f();
}
template<class Func>
void run(Func && f)
{
run2(std::forward<Func>(f));
}
int main()
{
run([s=BigState()]() { std::cout << "apply\n"; });
return 0;
}
Without using references, the BigState() will be copied when the lambda is copied.
UPDATE:
After reading the question again I see that it wants to restrict the signature
template<typename Func,
typename = std::enable_if_t<
std::is_convertible_v<decltype(Func(1)), int>>>
void run2(const Func & f)
{
std::cout << "Running\n";
f();
}
This will restrict it to any function that can accept int (possibly with an implicit cast), and returns an int or any type that is implicitly cast to int. However, if you want to accept only function-like objects that accept exactly int and return exactly int you can see if the lambda is convertible to std::function<int(int)>

Related

How to get the address of a C++ lambda function within the lambda itself?

I'm trying to figure out how to get the address of a lambda function within itself. Here is a sample code:
[]() {
std::cout << "Address of this lambda function is => " << ????
}();
I know that I can capture the lambda in a variable and print the address, but I want to do it in place when this anonymous function is executing.
Is there a simpler way to do so?
There is no way to directly get the address of a lambda object within a lambda prior to c++23.
Now, as it happens this is quite often useful. The most common use is in order to recurse.
The y_combinator comes from languages where you could not talk about yourself until you where defined. It can be implemented pretty easily in c++:
template<class F>
struct y_combinator {
F f;
template<class...Args>
decltype(auto) operator()(Args&&...args) const {
return f( f, std::forward<Args>(args)... );
}
template<class...Args>
decltype(auto) operator()(Args&&...args) {
return f( f, std::forward<Args>(args)... );
}
};
template<class F>
y_combinator(F)->y_combinator<F>;
now you can do this:
y_combinator{ [](auto& self)-> void {
std::cout<<"Address of this lambda function is => "<< &self;
} }();
There are a few useful variations. One variation I find particularly useful is:
template<class F>
struct y_combinator {
F f;
template<class...Args>
decltype(auto) operator()(Args&&...args) const {
return f( *this, std::forward<Args>(args)... );
}
template<class...Args>
decltype(auto) operator()(Args&&...args) {
return f( *this, std::forward<Args>(args)... );
}
};
where the self passed can be called without passing in self as the first argument.
The second matches the real y combinator (aka the fixed point combinator) I believe. Which you want depends on what you mean by 'address of lambda'.
There is also this pithy one:
template<class R, class...Args>
auto Y = [] (auto f) {
auto action = [=] (auto action) -> std::function<R(Args...)> {
return [=] (Args&&... args)->R {
return f( action(action), std::forward<Args>(args)... );
};
};
return action(action);
};
which returns a std function.
In c++23 accessing this within a lambda gets easier:
auto fib = [](this auto& self, int n) {
if (n < 2) return n;
return self(n-1) + self(n-2);
};
you can tag the first argument as this, and it becomes itself. It even works with the overload set trick, where self is the most-deduced type.
It is not directly possible.
However, lambda captures are classes and the address of an object coincides with the address of its first member. Hence, if you capture one object by value as the first capture, the address of the first capture corresponds to the address of the lambda object:
int main() {
int i = 0;
auto f = [i]() { printf("%p\n", &i); };
f();
printf("%p\n", &f);
}
Outputs:
0x7ffe8b80d820
0x7ffe8b80d820
Alternatively, you can create a decorator design pattern lambda that passes the reference to the lambda capture into its call operator:
template<class F>
auto decorate(F f) {
return [f](auto&&... args) mutable {
f(f, std::forward<decltype(args)>(args)...);
};
}
int main() {
auto f = decorate([](auto& that) { printf("%p\n", &that); });
f();
}
One way to solve this, would be to replace the lambda with a hand written functor class. It's also what the lambda essentially is under the hood.
Then you can get the address through this, even without ever assigning the functor to a variable:
#include <iostream>
class Functor
{
public:
void operator()() {
std::cout << "Address of this functor is => " << this;
}
};
int main()
{
Functor()();
return 0;
}
Output:
Address of this functor is => 0x7ffd4cd3a4df
This has the advantage that this is 100% portable, and extremely easy to reason about and understand.
Capture the lambda:
std::function<void ()> fn = [&fn]() {
std::cout << "My lambda is " << &fn << std::endl;
}
It is possible but highly depends on the platform and compiler optimization.
On most of the architectures I know, there is register called instruction pointer. The point of this solution is to extract it when we are inside the function.
On amd64 Following code should give you addresses close to the function one.
#include <iostream>
void* foo() {
void* n;
asm volatile("lea 0(%%rip), %%rax"
: "=a" (n));
return n;
}
auto boo = [](){
void* n;
asm volatile("lea 0(%%rip), %%rax"
: "=a" (n));
return n;
};
int main() {
std::cout<<"foo"<<'\n'<<((void*)&foo)<<'\n'<<foo()<<std::endl;
std::cout<<"boo"<<'\n'<<((void*)&boo)<<'\n'<<boo()<<std::endl;
}
But for example on gcc https://godbolt.org/z/dQXmHm with -O3 optimization level function might be inlined.

Keep a list of work to do in the future

Since function pointers need to know what arguments are supplied ahead of time I don't know how to do this.
Essentially I want a list of work. Each entry is a function to be called with specific arguments. I.e. I want to add foo(3, "abcd") to the work list, and then later bar(&h). That is, I don't know beforehand what types of functions will be added.
Later I will the iterate over this list and do the function calls specified.
Can this be implemented?
You're looking for std::function and either lambdas, or std::bind.
std::function is a wrapper for an arbitrary callable. You can store anything in it on which you can call operator() with the appropriate arguments.
One thing you can store in it are lambdas: you'd encapsulate the call and arguments into a non-argument lambda and call that.
Another thing you can store is the result of std::bind. std::bind is effectively a metafunction: it takes a function f and arguments as input, and returns a function object whose invocation results in invoking f on the arguments.
Here's how you could apply this to your case. The common setup:
std::vector<std::function<void()>> workList;
fillWorkList(workList);
for (auto& f : workList)
f();
And here are two possible implementations of fillWorkList. One with std::bind:
void fillWorkList(std::vector<std::function<void()>>& workList)
{
workList.push_back(std::bind(foo, 3, "abcd"));
workList.push_back(std::bind(bar, &h));
}
And one with lambdas:
void fillWorkList(std::vector<std::function<void()>>& workList)
{
workList.push_back([]() { foo(3, "abcd"); });
workList.push_back([]() { bar(&h); });
}
A std::function<void()> represents something that can be invoked, and returns nothing.
The clearest thing to store in it is a lambda.
std::function<void()> f = []{ foo(3, "abcd"); };
stores "call foo( 3, "abcd" ); in the std::function called f.
We can build a list of them -- a std::deque or std::vector -- and call them at a later time.
You can capture state in a lambda by putting what you want to capture within the []s:
std::function<void()> g = [h]{ bar(&h); };
This copies h into the lambda, then calls bar with a pointer to h. Sometimes you'll want h to be mutable:
std::function<void()> g = [h]()mutable{ bar(&h); };
You can also have lambdas that store references to variables. This is dangerous, as you are responsible for lifetime, and if you are storing the lambdas within std::functions then storing those in a container, lifetime may not be simple.
In C++14 you can even put expressions in the []s.
std::function<void()> behaves like a value. You invoke it with (), just like calling a function with signature void().
Using std::bind instead of lambdas is technically possible, but std::bind has many strange quirks and the code generated is usually less clear and errors are almost always unreadable. Don't do it.
You can also do this with a custom function object.
struct custom {
std::string s;
void operator()() const {
foo( 3, s );
}
};
Then std::function<void()> f = custom{ "abcd" }; is another way to say you'll invoke foo with 3, std::string("abcd") later when you f() on f.
Here is a solution, using a parameter pack, and perfect forwarding that allows for add(foo, 3, "abcd") to be used:
#include <functional>
#include <string>
#include <iostream>
#include <vector>
#include <utility>
void foo(int val, std::string text) { std::cout << val << '\t' << text << '\n'; }
void bar(int* ptr) { std::cout << *ptr << '\n'; }
class Worklist {
public:
template <typename ...Args>
void add(Args&&... args) {
worklist.push_back(std::bind(std::forward<Args>(args)...));
}
void do_all()
{
for(auto& i : worklist) {
i();
}
}
std::vector<std::function<void(void)>> worklist;
};
int main()
{
int h{9};
Worklist worklist;
worklist.add(foo, 3, "abcd");
worklist.add(bar,&h);
worklist.do_all();
}
It is possible to write a class that will accept lambdas as the tasks without using std::bind or std::function.
Here, a std::unique_ptr is used to store each of the lambdas:
#include <string>
#include <iostream>
#include <vector>
#include <memory>
#include <utility>
void foo(int val, std::string text) { std::cout << val << '\t' << text << '\n'; }
void bar(int* ptr) { std::cout << *ptr << '\n'; }
class Generic_Callable {
public:
~Generic_Callable() = default;
virtual void call() = 0;
};
template <typename T>
class MyCallable : public Generic_Callable {
public:
MyCallable(T &&t) : ptr{std::make_unique<T>(std::move(t))} {}
void call() override
{
(*ptr)();
}
std::unique_ptr<T> ptr;
};
class Worklist {
public:
template <typename T>
void add(T &&t)
{
worklist.push_back(std::make_unique<MyCallable<T>>(std::move(t)));
}
void do_all() {
for(auto& i : worklist)
i->call();
}
std::vector<std::unique_ptr<Generic_Callable>> worklist;
};
int main()
{
int h{9};
Worklist worklist;
worklist.add([]() {foo(3, "abcd"); });
worklist.add([&h]() {bar(&h); });
worklist.do_all();
}

When is a reference to function useful?

A reference to array parameter is useful because it prevents decay, allowing you to deduce the size of an array.
template <typename T, std::size_t N>
constexpr std::size_t array_size(T (&) [N]) noexcept
{
return N;
}
But when is this useful?
template<typename T>
void foo(T& t)
{
// we now have a reference to bar
}
void bar() { }
int main()
{
foo(bar);
}
When do we care about preventing function to pointer decay? I'm asking about when this is useful, not why it isn't disallowed.
Like with objects, we us a pointer if “no object” (“no function”) is a sensible value and a reference if we wish to make sure that (unless somebody insists to shoot himself in the foot) there is always a valid object (function) referred to.
Consider the following poor man's function wrapper (wealthy man goes over there).
template<typename>
class Function; // never defined
template<typename ReturnT, typename... ArgT>
class Function<ReturnT(ArgT...)>
{
private:
ReturnT (*func_)(ArgT...);
public:
// Will also accept a 'nullptr'
Function(ReturnT (*func)(ArgT...)) noexcept : func_ {func}
{
}
ReturnT
operator()(ArgT... args)
{
return this->func_(args...);
}
};
Now we can write the following program, which works just fine.
#include <iostream>
int
add(int a, int b)
{
return a + b;
}
int
main()
{
Function<int(int, int)> f {add}; // ok
std::cout << f(5, 7) << std::endl; // ok, prints 12
}
However, we can also write the following program, which doesn't work so nice.
int
main()
{
Function<int(int, int)> f {nullptr}; // compiles fine
std::cout << f(5, 7) << std::endl; // compiles fine, crashes at run-time
}
Instead, if we had replaced the (*func) with (&func) in the template's definition,
// Won't accept a 'nullptr'
Function(ReturnT (&func)(ArgT...)) noexcept : func_ {func}
{
}
the line
Function<int(int, int)> f {nullptr}; // compile-time error
would have triggered a compile-time error.
To me the difference is like between normal variable reference and a pointer. References are nicer to deal with than pointers.
I had a use-case when I to customize a parts of an algorithm. It had some phases and I could switch between several options for each phase. This is of course achievable with pointers, but hey, you can use pointers instead of references pretty much everywhere too.
It looked similar to this:
#include <iostream>
using namespace std;
class Foo
{
public:
Foo(void(&t)()) : barish(t) { };
void fun() {barish();};
private:
void(&barish)();
};
void bar() { cout << "meow\n";}
void bark() { cout << "woof\n";}
int main()
{
Foo foo1(bar);
Foo foo2(bark);
foo1.fun();
foo2.fun();
}
You can customize fun and don't have to deal with dereferencing and asserts that it's not null.

C++ 11 bound std::function vs storing tuple and unpacking

First off, I am still relatively new to C++11, so if I am missing anything, pardon my oversight. So what I am trying to do is basically have caller pass in a function and arbitrary # of arguments for that function, store that off and then call it asynchronously later on. And it seems there are 2 main options for this:
use std::bind to bind a std::function to its arguments (which is obtained using variadic template) and then invoke it later
convert the parameter pack into a tuple, store that and std::function, then unpack tuple into multiple args again and invoke function using that
Question is, is one way better than the other? Are there pro/cons/performance benefits of one over the other?
Thanks!
EDIT: as requested, here is a clarification, the first case is more early binding where I bind args to function as soon as caller passes them on and I store the bound func to be called later. the 2nd case is where I store func and args separately and invoke function with the args later on when it has to be called. So question is which is better performance/codesize/style/etc?
Accept a std::function<...> with the appropriate signature, store it to callback later. Let the caller decide how they prefer to create/populate the parameter. E.g.,
#include <functional>
#include <iostream>
std::function<int(int)> stored_f;
void set_callback(std::function<int(int)> f) {
stored_f = std::move(f);
}
void run_the_callback(int value) {
std::cout << stored_f(value) << '\n';
}
int f(int i) {
return i + 1;
}
int g(int a, int b) {
return a + b;
}
int main() {
// Plain old function pointer
set_callback(f);
run_the_callback(1);
// Use std::bind
set_callback(std::bind(g, 2, std::placeholders::_1));
run_the_callback(2);
// Use a lambda
set_callback([](int i){ return f(i) * g(i, i);});
run_the_callback(3);
}
Best performance - if you don't absolutely require type erasure of the callback - would be to parameterize your code on functor type. E.g.:
#include <functional>
#include <iostream>
template <typename Functor>
void do_stuff_and_callback_sometimes(Functor f) {
std::cout << f(1) << '\n';
// do some stuff, then
std::cout << f(2) << '\n';
// more work, and finally
std::cout << f(3) << "\n\n";
}
int f(int i) {
return i + 1;
}
int g(int a, int b) {
return a + b;
}
int main() {
// Plain old function pointer
do_stuff_and_callback_sometimes(f);
// Use std::bind
do_stuff_and_callback_sometimes(std::bind(g, 2, std::placeholders::_1));
// Use a lambda
do_stuff_and_callback_sometimes([](int i){ return f(i) * g(i, i);});
}
Avoiding type erasure is impossible in some situations, and in others will require you to jump through hoops. Whether or not it's worthwhile to do so is situational.
A third possibility is to move the responsibility of binding all the parameters to the caller, and only keep a std::function with the signature you intend to call.
For example:
struct Silly
{
using Callback = std::function<void()>;
void registerCallback(Callback cb) { callback_ = std::move(cb); }
Callback callback_;
};
This way it is quite obvious that it is the caller's responsibility to deal with lifetime, value vs. reference semantics for the arguments, etc.

c++ functor and function templates

consider this simple and pointless code.
#include <iostream>
struct A {
template<int N>
void test() {
std::cout << N << std::endl;
}
};
int main() {
A a;
a.test<1>();
}
It is a very simple example of a function template. What if however, I wanted to replace A::test with an overloaded operator() to make it a functor?
#include <iostream>
struct A {
template<int N>
void operator()() {
std::cout << N << std::endl;
}
};
int main() {
A a;
a<1>(); // <-- error, how do I do this?
}
Certainly if the operator() took parameters which were dependent on the template, the compiler could possibly deduce the template. But I just can't figure out the proper syntax to specify template parameters with a parameterless functor.
Is there a proper way to do this?
Obviously, this code would work since it bypasses the functor syntax:
a.operator()<1>();
but that kinda defeats the purpose of it being a functor :-P.
You can only call
a.operator()<1>();
but that would not be using a functor. Functors need a non template operator(), as they must be able to be called as varname() and that won't work with your code.
To make it a real functor change your code a template class (functors are classes):
#include <iostream>
template<int N>
struct A {
void operator()() {
std::cout << N << std::endl;
}
};
int main() {
A<1> a;
a();
}
There's not another "direct" way I know other than the:
a.operator()<1>();
syntax. If you're open to changing the code, moving the template parameter to the class would work, or using a (boost|tr1)::bind to make a (boost|tr1)::function object.
You are trying to pass a template parameter to an instance of an object, which as far as I know is not allowed. You can only pass templates parameters to template functions or template objects.
a.test<1>(); and a.operator()<1>(); work because they are serving as template functions.
Use boost::bind (check out boost libraries) to fix it though.
struct A {
void operator()(int n) {
std::cout << n << std::endl;
}
};
int main(int argc, char* argv[]) {
A a;
boost::function<void()> f = boost::bind<void>(a, 1);
f(); // prints 1
return 0;
}
And you don't even have to mess with templates!
You're stuck. Have you considered something like
struct A {
template<int N>
struct B
{
void operator()()
{ std::cout << N << std::endl; }
};
template<int N>
B<N> functor() {return B<N>();}
};
int main()
{
A a;
a.functor<1>()();
}
Nope, there's no way around it. Like you said, you have to either call the operator explicitly (which defeats the purpose), or the template arguments must be able to be deduced by the compiler.