std::function and default function arguments - c++

Here is simple example of using std::function
#include <iostream>
#include <functional>
//A function that sums two numbers.
//Arguments having default values.
void SumOfTwoNumbers(int a = 42, int b = 42)
{
std::cout << "Sum of two numbers :: " << a + b << std::endl;
}
int main()
{
std::function<void(int, int)> testFunc = SumOfTwoNumbers;
SumOfTwoNumbers(); //Works
testFunc(); //Compile time error
testFunc(40, 40); //Works
return 0;
}
In the main function, there are three function calls. The first one and the last one works. Whereas the second call testFunc() without any arguments gives compile time error.
Shouldn't it consider the default arguments and execute successfully?

No, the default values for function arguments are not part of the function signature. They are evaluated at the call site only.
You could use a lambda but then you'd need to redefine the default values:
auto testFunc = [](int a = 42, int b = 42) { SumOfTwoNumbers(a, b); };
... and storing such a lambda in a std::function would again result in the same problem since the signature of the lambda is also void(int, int).
You could however define your own wrapper functor (instead of using std::function) that has multiple operator() overloads:
struct {
void operator()() { SumOfTwoNumbers(42, 42); }
void operator()(int a) { SumOfTwoNumbers(a, 42); }
void operator()(int a, int b) { SumOfTwoNumbers(a, b); }
} testFunc;

Related

Is there a better way to provide this function to a constructor?

I have a class A which has a constructor with a function argument: i.e.
class A {
public:
A(int (*f)(int);
};
I can create this class and have it use func() with, for example,
int func(int n);
A a(func);
I would like to invoke this class a number of times, but have it use internally func(n)+m instead of func(n). I would prefer not to change class A. I could create a new class to define the function I want
class B {
int (*func)(int n);
int m;
public:
B(int (*ff)(int),int mm) : func(ff),m(mm) {}
int myfunc(int n) { return(func(n)+m);
};
However, I don't think it is possible to convert a pointer to myfunc into a pointer with the required signature for A's constructor.
The way I have chosen is similar to the above, but with myfunc() and associated variables stored in the global space:
int m;
int (*func)(int);
int myfunc(int n) { return(func(n)+m); }
void setupmyfunc(int mm,int (*ff)(int)) { m=mm; func=ff; }
Then I can can create my A object with
setupmyfunc(m,func);
A a(myfunc);
This works, but seems inelegant to me. Is there a better way?
Stateless lambdas are implicitly convertible to function pointers so you can just use that without modifying your class A and without creating another class B. That is if I understood your question correctly.
class A {
public:
A(int (*f)(int)) {};
};
int func(int n) { return n * 10; }
auto test()
{
A a{[](int n) { return func(n) + 1; }};
}
std::function can hold callable objects (functions, function objects, member function pointers (with object to bind to), etc. It uses some type-erasure such that it can have this genericity, but comes at the cost of internal overhead to actually invoke it, often equivalent to a virtual function call.
Here's an example, where A takes a std::function, which allows you to pass in lambdas.
#include <functional>
#include <iostream>
class A {
std::function<int(int)> func_;
public:
A(std::function<int(int)> func) : func_(func) {}
int call(int x) {
return func_(x);
}
};
int foo(int x) {
return x * 123; // whatever
}
int main() {
// here's your wrapper function to do func(x)+m (m==9 in this case)
A obj([](int x) { return foo(x) + 9; });
int result = obj.call(123);
std::cout << result << '\n';
}
https://godbolt.org/z/94MfGM67K
Update:
Given the rejection of both answers so far, using std::function is out because it changes class A, and the obvious use of state-full lambdas for composition and capturing customization data is also out, you will need to get more creative and possibly ugly. If you can't change A, then you can't change the signature of the function passed to a, so making the lambda take its data as another argument is also out.
Seems to me that leaves just one thing: using state that is outside the function (i.e. global data or encoded in a template non-type template parameter) as a form of pseudo-capture that an otherwise stateless function can use. I reject the global approach in general, though there's interesting aspects to it, and only present a template solution:
Now you write your free-standing functions and can compose them with a template:
#include <iostream>
using F = int(*)(int);
class A {
public:
A(F f) : f_(f) { }
int operator()(int x) { return f_(x); } // Added for demo
private:
F f_;
};
template <F FuncF, F FuncG>
int compose(int n) {
return FuncF(FuncG(n));
}
int func(int n) { return n * 1000; }
int add888(int n) { return n + 888; }
int add999(int n) { return n + 999; }
int main() {
A a1(compose<add888, func>);
A a2(compose<add999, func>);
std::cout << a1(1) << " " << a2(1) << " " << a1(1);
}
// output: 1888 1999 1888
https://godbolt.org/z/8KsqbTcTd
This works as far back as c++11, and replacing the "using" with "typedef" it work in C++98.

Call a C-style function address with std::bind and std::function.target using a method from object

I have a C-style function, which stores another function as an argument. I also have an object, which stores a method that must be passed to the aforementioned function. I built an example, to simulate the desired situation:
#include <functional>
#include <iostream>
void foo(void(*f)(int)) {
f(2);
}
class TestClass {
public:
std::function<void(int)> f;
void foo(int i) {
std::cout << i << "\n";
}
};
int main() {
TestClass t;
t.f = std::bind(&TestClass::foo, &t, std::placeholders::_1);
foo( t.f.target<void(int)>() );
return 0;
}
What is expected is that it will be shown on screen "2". But I'm having trouble compiling the code, getting the following message on the compiler:
error: const_cast to 'void *(*)(int)', which is not a reference, pointer-to-object, or pointer-to-data-member
return const_cast<_Functor*>(__func);
As I understand the use of "target", it should return a pointer in the format void () (int), related to the desired function through std :: bind. Why didn't the compiler understand it that way, and if it is not possible to use "target" to apply what I want, what would be the alternatives? I don't necessarily need to use std :: function, but I do need the method to be non-static.
This is a dirty little hack but should work
void foo(void(*f)(int)) {
f(2);
}
class TestClass {
public:
void foo(int i) {
std::cout << i << "\n";
}
};
static TestClass* global_variable_hack = nullptr;
void hacky_function(int x) {
global_variable_hack->foo(x);
}
int main() {
TestClass t;
global_variable_hack = &t;
foo(hacky_function);
return 0;
}
//can also be done with a lambda without the global stuff
int main() {
static TestClass t;
auto func = [](int x) {
t->foo(x); //does not need to be captured as it is static
};
foo(func); //non-capturing lambas are implicitly convertible to free functions
}

Call the same lambda several times in C++

Can lambda be reused?
I'd like to call this lambda a few times. But I can't find a way to give it a name.
[]() { cout << "lambda is called"; };
And what is the purpose of lambda without invoking like this? Compiler does not yell at the code above, but it is useless. Am I right?
You can give it a name using the auto specifier:
auto f = []() { cout << "lambda is called"; };
That will allow you to invoke it with f(). But bear in mind that the type of a lambda isn't specified, so if you want to pass it to functions, you'll need to use templates (or convert to std::function<void()>).
template <typename F>
void three_times(F g) {
g(); g(); g();
}
If you want to reuse a lambda you need to assign it to a variable.
auto lambda = []() { cout << "lambda is called"; };
gives you an object named lambda that you can call the operator () on to execute the body of the lambda like
lambda();
Yes lamda can be reused. See the example below
#include <iostream>
using namespace std;
template <typename F> void func2(F f) {
f("func2");
}
void func(function<void(const char *)> f) {
f("func");
}
int main() {
auto l = [](const char *s) {
cout << s << "\n";
};
for (int i = 0; i < 2; i++) {
l("main"); // Calling lambda multiple times
func(l); // Passing lambda to a function using function<>
func2(l); // Passing lambda to a function using template
}
return 0;
}
Output:
main
func
func2
main
func
func2
You can easily give a lambda a name by assigning it to an auto variable - like so;
const auto l = [] { whatever };
Then call l multiple times as l(); .
Store the lambda using auto
or assign it to a compatible std::function explicitly:
auto f1 = [](int x, int y)->float{ ..... };
std::function<float(int,int)> f2 = [](int x, int y)->float{ ..... };
float x = f1(3,4);
auto y = f2(5,6);
std::function<float(int,int)> f3 = f1;

how to call a function passed as argument with its parameters already given in D?

I need to call a function passed as argument to another function and it must be passed its needed arguments firstly. In c++, this problem is solved with a macro:
#include <iostream>
#define CALL(x) x; \
std::cout << "Called!" << std::endl;
void foo(int a, int b)
{
std::cout << a * b << std::endl;
}
int main()
{
CALL(foo(9, 8)); // I want to pass 2 int parameters inside 'foo' function call
system("PAUSE");
}
It sould output:
> 72
> Called!
That is exactly how I need to call the function in D. Any ideas?
Edit:
I need this to be done in D. I want to call "foo" inside CALL like:
CALL(foo(9, 8)) // and not like: CALL(foo, 9, 8)
But I don't know how this is achieved in D. Perhaps with a mixin?
In D, you can use a lazy function parameter for this.
import std.stdio;
void CALL(lazy void x) {
writeln("before called");
x;
writeln("after called");
}
void foo(int x, int y) {
writeln(x, " ", y);
}
void main() {
CALL(foo(3, 5));
}
D's lazy parameter storage class causes the compiler to wrap whatever you give it in a little anonymous function. The above is as if you wrote:
import std.stdio;
void CALL(void delegate() x) { // note delegate here in long-form syntax
writeln("before called");
x();
writeln("after called");
}
void foo(int x, int y) {
writeln(x, " ", y);
}
void main() {
// and this delegate too
CALL( delegate() { return foo(3, 5); } );
}
But the compiler rewrites it for you. This is why I said lazy void - the void there is the return type of the hidden function you pass. If it returned int, you could use lazy int instead.
Note that since x inside the CALL function is rewritten to be a hidden function, calling it twice will actually evaluate the arguments twice:
void CALL(lazy void x) {
writeln("before called");
x;
writeln("after called");
x;
writeln("after called again");
}
would do:
before called
3 5
after called
3 5
after called again
Notice how it printed out the arguments twice. Just like the C macro, actually. But if that's not what you want, simply assign it to a temporary yourself:
void CALL(lazy int x) {
auto tmp = x;
// you can now use tmp as a plain int
}

How to include arguments in a function pointer?

How can I include arguments in a function pointer?
This code creates a function pointer that can add two ints:
int addInt(int n, int m) {
return n+m;
}
int (*functionPtr)(int,int);
functionPtr = addInt;
(*functionPtr)(3,5); // = 8
For instance, I want to make a function pointer where the first argument is always 5, so that the function takes one int and adds five. And another one where the first argument is 8.
Is this possible using addInt? Something like:
// make-believe code that of course won't work
int (*functionPtr)(int);
functionPtr = addInt(5);
(*functionPtr)(3); // = 8
(*functionPtr)(9); // = 14
Use std::bind like this:
using namespace std::placeholders;
auto f = std::bind(addInt, 5, _1);
f(1); //returns 6
Use std::bind and placeholders
#include <iostream>
#include <functional>
using namespace std;
int addInt(int n, int m) {
return n+m;
}
int main() {
int (*functionPtr)(int,int);
functionPtr = addInt;
(*functionPtr)(3,5); // = 8
auto f2 = std::bind( addInt, std::placeholders::_1, 5);
auto f3 = std::bind( addInt, 8, std::placeholders::_1);
std::cout << f2(1) << "\n";;
std::cout << f3(1) << "\n";;
}
Output:
6
9
What you really want is a closure (you might also want curryfication, but C++ don't have that; consider switching to Ocaml if you really want it).
C+14 and C++11 have closures (but not earlier versions of C++). Read about C++ lambda functions (or anonymous functions) and the standard <functional> header and its std::function template.
Here is the function which given some integer d returns the translation by d i.e. the function taking an integer x and returning x+d
#include <functional>
std::function<int(int)> translation(int d) {
return [=](int x) { return addInt(x,d) /* or x+d */ ; };
}
Notice that std::function-s are not just C function pointers. They also contain closed values (d in my translation example)
The auto and decltype specifiers are tremendously useful.
For example:
auto addfive = translation(5);
std::cout << addfive(3) << std::end; // should output 8