This code generates a SIGSEGV on runtime when compiled with GCC (4.7.2-5ubuntu) but not Clang (Apple LLVM 4.2)
#include <functional>
#include <iostream>
using FuncType = std::function<int(int)>;
int func(FuncType f, int i) {
return f(i)+1;
}
struct Alpha {
FuncType f, g;
Alpha(FuncType f) : f(f) {
g = [&](int i) -> int {
return func(f, i);
};
}
int go(int i) {
return g(i);
}
};
struct Beta {
int k = 0;
Beta newBeta(int nk) {
Beta beta = *this;
beta.k = nk;
return beta;
}
};
struct Gamma {
Beta beta;
void go(int j) {
auto f = [&](int i) -> int {
int n = beta.newBeta(i).k+j;
return n*n;
};
Alpha alpha(f);
std::cout << alpha.go(beta.k) << std::endl;
}
};
int main(int argc, char *argv[]) {
Gamma gamma;
gamma.go(7);
return 0;
}
Debugging, the crash occurs when the lambda f is called in func. beta reports as an invalid object, even though it should still be valid when the lambda is called.
It looks as though this is a result of this bug, but that bug was reportedly fixed in 4.7.2.
Edit: Initialized Beta::k for clarity, does not affect bug.
One problem is here:
Alpha(FuncType f) : f(f) {
g = [&](int i) -> int {
return func(f, i);
};
}
your lambda is binding f (an argument to the contructor and so local to the constructor) by reference, so after the constructor completes, that reference is dangling. When you later call g, you get undefined behavior as it refers to this dangling reference.
Change the [&] to [=] to bind by value and it should be ok.
Related
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;
}
Trying to call a function that gets used as an argument for another function, while passing it's own arguments. Example in pseudoish c++ code:
void function1(argument(x)) ///I believe this should be void function1(void(*argument)(int)), but i try to call it as *argument(); and that fails also
{
doStuff;
argument(x);
doMoreStuff;
}
void function2(int x)
{
int test;
test = x + 2;
doOtherStuffWithx;
}
int main()
{
int test = 1;
sample = function1(function2(test));
}
haven't been able to figure it out. Any help would be greatly appreciated.
The simplest for you would be to program it like that:
#include <functional>
void function1(std::function<void(int)> func, int arg)
{
//doStuff;
func(arg);
//doMoreStuff;
}
void function2(int x)
{
int test;
test = x + 2;
//doOtherStuffWithx;
}
int main()
{
int test = 1;
function1(function2, test);
}
If you want to use some function with arbitrary number of arguments and types, then you can use templates:
template<typename F, typename... Args>
void function1(F&& func, Args&&... args)
{
//doStuff;
func(std::forward<Args>(args)...);
//doMoreStuff;
}
The simplest way to do this is to use a lambda expression calling the function with the desired parameter, and pass that as a std::function that your function1() accepts:
#include <iostream>
#include <functional>
void function1(std::function<void()> f)
{
std::cout << "Stuff before...\n";
f();
std::cout << "... stuff after.\n";
}
void function2(int x)
{
int test;
test = x + 2;
std::cout << test << '\n';
}
int main()
{
int test = 1;
function1([=]() { function2(test); });
}
This code prints 0 (with no optimization) or 666 (with optimizations turned on) when built with clang++ -std=c++11 (-O3 yields 666, which is what I would expect). When lambda is passed by universal reference the problem disappears.
FYI, GCC prints 666 on all the versions I've tested.
Is it a compiler bug or the code is incorrect?
#include <memory>
#include <iostream>
template <typename T>
std::shared_ptr<void> onScopeExit(T f)
{
return std::shared_ptr<void>((void*)1, [&](void *) {
f();
});
}
struct A {
void f() {
auto scopeGuard = onScopeExit([&]() { i = 666; }); // [1]
// ... (some work)
} // (lambda [1] being ? called on scope exit)
int i = 0;
};
A a;
int main() {
a.f();
std::cout << a.i << std::endl;
}
The compiler in question is:
Apple LLVM version 9.1.0 (clang-902.0.39.2)
Target: x86_64-apple-darwin17.7.0
Your code has undefined behavior. You capture f by reference in onScopeExit but once you return the shared_ptr from the function the deleter is now holding a dangling reference to f, since f went out of scope. What you need to do is capture f by value, and then you won't have a dangling reference
template <typename T>
std::shared_ptr<void> onScopeExit(T f)
{
return std::shared_ptr<void>((void*)1, [=](void *) {
f();
});
}
struct A {
void f() {
auto scopeGuard = onScopeExit([&]() { i = 666; }); // [1]
// ... (some work)
} // (lambda [1] being ? called on scope exit)
int i = 0;
};
A a;
int main() {
a.f();
std::cout << a.i << std::endl;
}
I am unsure about a possible GCC bug in initialization of a std::function from a lambda function capturing this in a non-static data member initializer. Is this allowed by the C++ standard or is this UB?
Given the following code:
#include <functional>
#include <iostream>
template <typename T>
struct A {
T x = 0;
std::function<void(T)> f = [this](T v) { x = v; };
};
int main() {
A<int> a;
a.f(1);
std::cout << a.x << "\n";
}
In my understanding, it should print 1. However, when built with GCC 5.4.0 or GCC 6.2.0, a.f(1) emits a segmentation fault, because the captured this pointer is null.
The following alternatives work as I expected:
Using constructor initializer list:
template <typename T>
struct B {
B() : f([this](T v) { x = v; }) {}
T x = 0;
std::function<void(T)> f;
};
Without template:
struct C {
int x = 0;
std::function<void(int)> f = [this](int v) { x = v; };
};
Also, when built with Clang 3.8.0, all three versions behave as I expect, which doesn't mean it is not UB.
You cannot do:
template <typename T>
struct A {
T x = 0;
std::function<void(T)> f = [this](T v) { x = v; };
};
As this does not exist when you define f. You need to initilize f in a constructor, such as:
A(){ f = [this](T v){ x=v; } }
It worked with G++4.8.
Your code compiles and runs on VS2015 (windows).
So this is probably a compiler error.
Also, if you will remove the template it works on http://cpp.sh/
Try this code:
#include <functional>
#include <iostream>
struct A {
int x = 0;
std::function<void(int)> f = [this](int v) { x = v; };
};
int main() {
A a;
a.f(1);
std::cout << a.x << "\n";
}
running original code on cpp.sh gives:
internal compiler error: in tsubst_copy, at cp/pt.c:12569
Please submit a full bug report
So I guess it's a bug
I'm trying to write a class that takes, as a constructor parameter, a factory function that creates another instance of the same class on a transformed version of the input. For a trivial example, a functor class that takes an int, prints it, and returns another functor that prints the input's successor.
I'm getting errors of the form
error: could not convert 'foo' from 'Type(*)(int)' to 'std::function<Type(int)>'
The only seems to arise with factory functions passed into constructors.
Using a function pointer instead of a std::function<> works fine, but I was hoping that with C++11 I'd be able to avoid function pointers.
Here's an example:
#include <functional>
#include <iostream>
// std::function-returning-int param in ctor with default value
// This works fine
class PrInc; // "print and increment"
using Worker = std::function<int(int)>;
int foo(int i) {
std::cout << i << std::endl;
return i+1;
}
class PrInc {
public:
PrInc(int i, Worker fn = foo) : i_(i), fn_(fn) {}
int operator()() { return fn_(i_); }
private:
int i_;
Worker fn_;
};
// std::function-returning-PrInc2 param in ctor with default value
// This fails, at least on g++ 4.8.2 --std=c++11
class PrInc2;
using Factory = std::function<PrInc2(int)>;
// Use function ptrs (instead of std::function<>s) and it works fine
//typedef PrInc2 (*Factory)(int);
PrInc2 bar(int);
class PrInc2 {
public:
PrInc2(int i, Factory fn = bar) : i_(i), fn_(fn) {}
PrInc2 operator()() { return fn_(i_); }
private:
int i_;
Factory fn_;
};
PrInc2 bar(int i) {
std::cout << i << std::endl;
return PrInc2(i+1);
// error: could not convert 'bar' from 'PrInc2 (*)(int) to 'Factory {aka std::function<PrInc2(int)>'
}
int main() {
auto p1 = PrInc {1};
auto p2 = PrInc{p1()};
p2();
auto p3 = PrInc2 {1};
// error: could not convert 'bar' from 'PrInc2 (*)(int) to 'Factory {aka std::function<PrInc2(int)>'
auto p4 = p3();
p4();
return 0;
}
What am I doing wrong?
EDIT: thelink2012's suggestion to try PrInc2(int i, Factory fn = Factory(bar)) works fine on the "repro" above, but fails on the motivating example (GitHub link; relevant code is erdos.h:35-54 around ParseStep and ParseFunction). Back to the drawing board for a better repro....
The following part of your code, which is the only part that appears to be relevant to the compiler error you're asking about, compiles cleanly with gcc 4.9.2 using the -std=c++11 mode:
#include <functional>
#include <iostream>
using Worker = std::function<int(int)>;
int foo(int i) {
std::cout << i << std::endl;
return i+1;
}
class PrInc {
public:
PrInc(int i, Worker fn = foo) : i_(i), fn_(fn) {}
int operator()() { return fn_(i_); }
private:
int i_;
Worker fn_;
};
Most likely a bug in the older gcc you're using. Upgrade to a more recent version of gcc.