I'm trying to write a demo to chain various functions into one, just like chain(f, g)(x) = g(f(x))
, it is OK when I chain lambdas, but with named functions, I got a segmentation fault, I'm now struggling with it.
My code:
template <typename F, typename G>
constexpr auto chain(F&& f, G&& g) {
return [&](auto x) {
return g(f(x));
};
}
template <typename F, typename... Fs>
constexpr auto chain(F&& f, Fs&&... fs) {
return chain(f, chain(fs...));
}
int add1(int x) {
return x + 1;
}
int times2(int x) {
return x * 2;
}
int add10(int x) {
return x + 10;
}
int main(int argc, char* argv[]) {
auto f = chain(
[](int x) { return x + 1; },
[](int x) { return x * 2; },
[](int x) { return x + 10; });
printf("result: %d\n", f(2)); // Here is OK
auto g = chain(add1, times2, add10);
printf("result: %d\n", g(2)); // Here I got a segmentation fault and I don't know why
return 0;
}
Your non-variadic chain
function template returns a lambda that captures the arguments f
and g
by reference. These references are dangling when you return from chain
, and invoking the returned lambda invokes undefined behavior.
As is the case with undefined behavior, it can appear to work sometimes, and can cause a segmentation fault at other times. There is of course no guarantee of this behavior.