I'm trying to write the “plus2” and “plus3” functions that implement the functions, respectively, and are defined as follows.
f is a function such that expression (x) (y) should result in the value of x + y.
g is a function such that expression (x) (y) (z) should result in the value of x + y + z. Here, x, y, z are integers.
#include <functional>
#include <iostream>
std::function<int(int)> plus2(int n) {
return [n](int x) { return x + n; };
}
std::function<int(int)> plus3(int f(int), int n) {
return [f, n](int x) { return f(n) + x; };
}
int main() {
std::cout<<plus2(1)(2)<<" "<<plus3(1)(2)(3);
return 0;
}
OUTPUT should be: 3 6
I get an error
too few arguments to function ‘std::function<int(int)> plus3(int
(*)(int), int)’
Function plus2 works fine. Could you explain me where I'm making mistake in function plus3?
Function plus2 works fine.
Because plus2 is a function that expects 1 parameter and returns a function that expects 1 parameter.
plus3 on the other hand is a function that expects 2 parameters. You cannot call it with only one parameter. You can turn it into a function that expects one parameter and returns a callable that returns a callable.
I suppose this is just an exercise to learn lambdas, because otherwise I see no reason to write the functions like this. At least you should use auto return type to avoid unnecessary conversion to std::function (*):
#include <iostream>
auto plus3(int n) {
return [n](int a) { return [b=a+n](int c){ return b+c;} ;};
}
int main(int argc, char* argv[]){
std::cout << plus3(1)(2)(3);
}
(*): std::function is not the type you should use whenever you want to pass a callable around. Rather it is the type to be used when you need one type that can store any kind of callable. std::function uses type erasure to achieve that. If you do not need that then you do not need std::function.
It looks like you are practicing the subject of currying in functional programming (Currying - Wikipedia).
If you want to write plus3 as a curried function you can do the following (no change in plus2):
#include <functional>
#include <iostream>
auto plus2(int n) {
return [n](int x) { return x + n; };
}
auto plus3(int n) {
return [n](int m) {
return [n, m](int x) { return x + n + m; }; };
}
int main() {
std::cout << plus2(1)(2) << " " << plus3(1)(2)(3);
return 0;
}
plus3 should take an int and produce a function.
It should not take a function and an int.
The resulting function should take an int and then proceed as plus2.
It's a nice touch to reuse plus2:
std::function<std::function<int(int)>(int)> plus3(int n) {
return [n](int x) { return plus2(n+x); };
}
Slightly more readable with a type alias:
using int_to_int = std::function<int(int)>;
std::function<int_to_int(int)> plus3(int n) {
return [n](int x) { return plus2(n+x); };
}
and even more readable with auto (although it's not equivalent since it doesn't give the same type):
auto plus3(int n) {
return [n](int x) { return plus2(n+x); };
}
and now you can generalize:
template<size_t n>
auto plus(int x)
{
return [x](int y) { return plus<n-1>(x+y); };
}
template<>
auto plus<1>(int x) { return x; }
int main() {
std::cout << plus<2>(1)(2) << std::endl << plus<4>(1)(2)(3)(4) << std::endl;
}
Related
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;
I know that I shouldn't overload a function for just parameters differ only in one of them passed by copy and the other by reference:
void foo(int x)
{
cout << "in foo(int x) x: " << x << endl;
}
void foo(int& x)
{
cout << "in foo(int& x) x: " << x << endl;
}
int main()
{
int a = 1;
foo(5); // ok as long as there is one best match foo(int)
foo(a); // error: two best candidates so the call is ambiguous
//foo(std::move(a));
//foo(std::ref(an)); // why also this doesn't work?
}
So a code that uses std::bind can be like this:
std::ostream& printVec(std::ostream& out, const std::vector<int> v)
{
for (auto i : v)
out << i << ", ";
return out;
}
int main()
{
//auto func = std::bind(std::cout, std::placeholders::_1); // error: stream objects cannot be passed by value
auto func = std::bind(std::ref(std::cout), std::placeholders::_1); // ok.
}
So std::ref here to ensure passing by reference rather than by value to avoid ambiguity?
* The thing that matters me: Does std::bind() implemented some wrapper to overcome this issue?
Why I can't use std::ref in my example to help the compiler in function matching?
Now that you know passing by value and reference are ambiguous when overload resolution tries to compare them for choosing a best viable function, let's answer how would you use std::ref (or std::cref) to differentiate between pass-by-value and pass-by-reference.
It turns out to be ... pretty simple. Just write the overloads such that one accepts a int, and the other accepts a std::reference_wrapper<int>:
#include <functional>
#include <iostream>
void foo(int x) {
std::cout << "Passed by value.\n";
}
void foo(std::reference_wrapper<int> x) {
std::cout << "Passed by reference.\n";
int& ref_x = x;
ref_x = 42;
/* Do whatever you want with ref_x. */
}
int main() {
int x = 0;
foo(x);
foo(std::ref(x));
std::cout << x << "\n";
return 0;
}
Output:
Passed by value.
Passed by reference.
42
The function pass the argument by value by default. If you want to pass by reference, use std::ref explicitly.
Now let's answer your second question: how does std::bind deal with this type of scenario. Here is a simple demo I have created:
#include <functional>
#include <type_traits>
#include <iostream>
template <typename T>
struct Storage {
T data;
};
template <typename T>
struct unwrap_reference {
using type = T;
};
template <typename T>
struct unwrap_reference<std::reference_wrapper<T>> {
using type = std::add_lvalue_reference_t<T>;
};
template <typename T>
using transform_to_storage_type = Storage<typename unwrap_reference<std::decay_t<T>>::type>;
template <typename T>
auto make_storage(T&& obj) -> transform_to_storage_type<T> {
return transform_to_storage_type<T> { std::forward<T>(obj) };
}
int main() {
int a = 0, b = 0, c = 0;
auto storage_a = make_storage(a);
auto storage_b = make_storage(std::ref(b));
auto storage_c = make_storage(std::cref(c));
storage_a.data = 42;
storage_b.data = 42;
// storage_c.data = 42; // Compile error: Cannot modify const.
// 0 42 0
std::cout << a << " " << b << " " << c << "\n";
return 0;
}
It is not std::bind, but the method used is similar (it's also similar to std::make_tuple, which has the same semantic). make_storage by default copies the parameter, unless you explicitly use std::ref.
As you can see, std::ref is not magic. You need to do something extra for it to work, which in our case is to first decay the type (all references are removed in this process), and then check whether the final type is a reference_wrapper or not; if it is, unwrap it.
I would like to visit a "recursive" std::variant using lambdas and overload-creating functions (e.g. boost::hana::overload).
Let's assume I have a variant type called my_variant which can store one an int, a float or a vector<my_variant>:
struct my_variant_wrapper;
using my_variant =
std::variant<int, float, std::vector<my_variant_wrapper>>;
struct my_variant_wrapper
{
my_variant _v;
};
(I'm using a wrapper my_variant_wrapper class in order to define the variant type recursively.)
I want to recursively visit the variant printing different things depending on the stored types. Here's a working example using a struct-based visitor:
struct struct_visitor
{
void operator()(int x) const { std::cout << x << "i\n"; }
void operator()(float x) const { std::cout << x << "f\n"; }
void operator()(const std::vector<my_variant_wrapper>& x) const
{
for(const auto& y : x) std::visit(*this, y._v);
}
};
Calling std::visit with the above visitor prints the desired output:
my_variant v{
std::vector<my_variant_wrapper>{
my_variant_wrapper{45},
std::vector<my_variant_wrapper>{
my_variant_wrapper{1}, my_variant_wrapper{2}
},
my_variant_wrapper{33.f}
}
};
std::visit(struct_visitor{}, v);
// Prints:
/*
45i
1i
2i
33f
*/
I would like to locally create the visitor as a series of overloaded lambdas using boost::hana::overload and boost::hana::fix.
fix is an implementation of the Y-combinator, which can be used to implement recursion in type-deduced lambdas. (See this question for more information.)
This is what I tried, and expected to work:
namespace bh = boost::hana;
auto lambda_visitor = bh::fix([](auto self, const auto& x)
{
bh::overload(
[](int y){ std::cout << y << "i\n"; },
[](float y){ std::cout << y << "f\n"; },
[&self](const std::vector<my_variant_wrapper>& y)
{
for(const auto& z : y) std::visit(self, z._v);
})(x);
});
My reasoning is as follows:
boost::hana::fix returns an unary generic lambda that can be used as the visitor for an std::variant.
boost::hana::fix takes a binary generic lambda where the first parameter is an unary function that allows recursion of the lambda, and the second parameter is the initial argument for the body of the lambda.
Calling boost::hana::overload with handlers for all the possible types inside my_variant creates some sort of visitor which is equivalent to struct_visitor.
Using self instead of lambda_visitor inside the const std::vector<my_variant_wrapper>& overload should allow recursion to work properly.
Immediately calling the created overload with bh::overload(...)(x) should trigger the recursive visitation.
Unfortunately, as you can see in this wandbox example, the lambda_visitor example fails to compile, spewing out a lot of almost-undecipherable template-heavy errors:
...
/usr/local/boost-1.61.0/include/boost/hana/functional/fix.hpp:74:50: error: use of 'main():: [with auto:2 = boost::hana::fix_t >; auto:3 = int]' before deduction of 'auto'
{ return f(fix(f), static_cast(x)...); }
...
The error seems similar to what I would get without using boost::hana::fix:
auto lambda_visitor = bh::overload(
[](int y){ std::cout << y << "i\n"; },
[](float y){ std::cout << y << "f\n"; },
[](const std::vector<my_variant_wrapper>& y)
{
for(const auto& z : y) std::visit(lambda_visitor, z._v);
});
std::visit(lambda_visitor, v);
error: use of 'lambda_visitor' before deduction of 'auto'
for(const auto& z : y) std::visit(lambda_visitor, z._v);
What am I doing wrong? Is it possible to achieve local recursive variant visitation using fix, overload and a set of lambdas?
My intuition was that lambda_visitor would have been "equivalent" to struct_visitor, thanks to the indirection offered by fix.
Let's pick a simpler example. We want to implement gcd using the fix-point combinator. First go might be something like:
auto gcd = bh::fix([](auto self, int a, int b) {
return b == 0 ? a : self(b, a%b);
});
std::cout << gcd(12, 18);
This fails to compile with gcc ultimately producing this error:
/usr/local/boost-1.61.0/include/boost/hana/functional/fix.hpp:74:50: error: use of 'main()::<lambda(auto:2, int, int)> [with auto:2 = boost::hana::fix_t<main()::<lambda(auto:2, int, int)> >]' before deduction of 'auto'
{ return f(fix(f), static_cast<X&&>(x)...); }
^
The lambda we're passing to fix() has a deduced return type. But how do we deduce it? There's only a single return statement, and that one is recursive! We need to give the compiler some help. Either we need to break apart our return statement so that one has a clear type:
auto gcd = bh::fix([](auto self, int a, int b) {
if (b == 0) {
return a;
}
else {
return self(b, a%b);
}
});
or simply provide the return type explicitly:
auto gcd = bh::fix([](auto self, int a, int b) -> int {
return b == 0 ? a : self(b, a%b);
});
Both of these options compile and work.
The same is true of your original example. If you just specify that the lambda returns void, everything works:
auto lambda_visitor = bh::fix([](auto self, const auto& x) -> void
// ^^^^^^^^
{
bh::overload(
[](int y){ std::cout << y << "i\n"; },
[](float y){ std::cout << y << "f\n"; },
[&self](const std::vector<my_variant_wrapper>& y)
{
for(const auto& z : y) std::visit(self, z._v);
})(x);
});
std::visit(lambda_visitor, v);
In C++11 one can write lambdas with captures (and that's awesome!)
auto myfunc = [&] (int i) {return i + j;}; // j being somewhere in the lambda's context
That is awesome! However, it would be very nice if one could return such a lambda from a function, or even from another lambda. Is this possible at all?
In C++11, you'd have to wrap it in a function object of known type to return it from a function:
std::function<int(int)> get_lambda() {
return [&] (int i) {return i + j;};
}
In C++14, you can use auto to return the lambda type itself:
auto get_lambda() {
return [&] (int i) {return i + j;};
}
In either dialect, you could return it from a lambda:
auto get_lambda = [&] {return [&] (int i) {return i + j;};};
Note that you wouldn't want to return this particular lambda, since it captures a reference to a local variable j. The variable will be destroyed, leaving the reference invalid, when the function returns.
You can return a lambda with captures. Since c++14 introduced automatic return types this is particularly easy.
Here's an example of how to create a function that will apply a binary operator (multiplication here, but it's a template parameter so you can give it anything) with one argument fixed during creation and the second provided during calling
#include <iostream>
#include <functional>
template<typename F, typename T>
auto opby(F func, T arg)
{
return [=](auto val) {
return func(val, arg);
};
}
int main()
{
auto mu = opby(std::multiplies<int>(), 2);
std::cout << mu(3) << std::endl;
}
it prints 6. The returned lambda had captured by value its enclosing scope so a function is created that will multiply by two any argument you'll give it.
The only caveat is when capturing by reference : you have to ensure that the closure won't transcend the lifetime of captured objects.
I would like to provide a simple example of the accepted answer.
#include <iostream>
using namespace std;
auto get_lambda(int j) {
//capture by value here
return [=](int i) {return i + j; };
}
int main() {
auto f = get_lambda(3);
for (int i = 0; i < 1000; i++) {
cout << f(i) << endl;
}
}
This looks just like the closure in JavaScript and Python. Horraayy!
So I have the following code:
#include <iostream>
template <typename T>
class funcky
{
public:
funcky(char const* funcName, T func)
: name(funcName), myFunc(func)
{
}
//private:
char const* name;
T myFunc;
};
#if 0
int main(void)
{
char const* out = "nothing";
// requires template args
funcky test("hello", [&](int x, int y) -> int
{
out = "YES";
return x + y;
});
std::cout << test.name << " = " << test.myFunc(1, 2) << std::endl;
std::cout << test.name << " = " << out << std::endl;
return 0;
}
int main2(void)
{
funcky<void(*)(void)> test("hello", [&, this](void) -> void
{
std::cout << this->name << std::endl;
});
test.myFunc();
return 0;
}
#endif
int main(void)
{
char const* out = "nothing";
auto myFunc = [&](int x, int y) -> int
{
out = "YES";
return x + y;
};
funcky<decltype(myFunc)> test("hello", myFunc);
std::cout << test.name << " = " << test.myFunc(1, 2) << std::endl;
std::cout << test.name << " = " << out << std::endl;
return 0;
}
The top chunk is a function holder that holds a lambda and a name for it.
Next is what I'd like to use API-wise, but fails due to no template arguments being specified.
After that, there's my wondering if it's possible to have a 'this' of a specific type (such as funcky) be used in a lambda not declared inside it. Wishful thinking.
At the very end is code that compiles but uses a lambda outside the funcky constructor and decltype.
Are such things possible in C++11? How I accomplish said things?
Also unless it can kind of have the same API, try not to guess what I'm doing as if I can't do it this way, I'll just rewrite it in a simpler way. It's not worth the effort.
If you want to provide a way for a user to supply a callback to your class, you're better off using std::function, since templating the class on the function / functor type is not a very useful thing to do, as you experienced.
The problem arises from the fact that you can't just take anything in. You should have clear requirements on what can be passed as a callback, since you should know how you want to call it later on. See this on why I make the constructor a template.
#include <functional>
#include <utility>
struct X{
template<class F>
X(F&& f) : _callback(std::forward<F>(f)) {} // take anything and stuff it in the 'std::function'
private:
std::function<int(int,int)> _callback;
};
int main(){
X x([](int a, int b){ return a + b; });
}
If, however, you don't know how the callback is going to be called (say, the user passes the arguments later on), but you want to support that, template your type on the signature of the callback:
#include <iostream>
#include <functional>
#include <utility>
template<class Signature>
struct X{
template<class F>
X(F&& f) : _callback(std::forward<F>(f)) {} // take anything and stuff it in the 'std::function'
private:
std::function<Signature> _callback;
};
int main(){
X<int(int,int)> x1([](int a, int b){ return a + b; });
X<void()> x2([]{ std::cout << "wuzzah\n";});
}
Something like
template<typename Functor>
funcky<typename std::decay<Functor>::type>
make_funcky(const char* name, Functor&& functor)
{ return { name, std::forward<Functor>(functor) }; }
can be helpful for things like:
auto test = make_funcky("hello", [&](int x, int y) -> int
{
out = "YES";
return x + y;
});
However, inside a lambda expression this always refers to the immediate this outside of the expression. It's not a delayed reference to some this present at the time of the invocation -- it's not an implicit parameter. As such it doesn't make sense to want 'another type' for it.