"Definitely not after storing it in a std function. Without that, I could do it with a horrible (yet legal) hack in C++17. But I would be a horrible person to tell you how, because you might use it." – Yakk
Well let's relieve Yakk's karma; here's a proof of concept of a C++14 solution which you definitely don't want to let loose in the wild:
auto magic = [a, b](auto &&... args) mutable -> decltype(auto) {
return makeOverload(
// Capture access boilerplate
[&](cap_<0>) -> auto& { return a; },
[&](cap_<1>) -> auto& { return b; },
// Actual function
[&](int p) {
return "[" + std::to_string(a) + ", " + b + "](" + std::to_string(p) + ")";
}
)(std::forward<decltype(args)>(args)...);
};
makeOverload
takes any number of functors and blends them into a single one. I borrowed the idea from this blog post, with help from the comment section to make it actually work.
The resulting functor is used to tag-dispatch between the cap<N>
tags and the actual parameters of the function. Thus, calling magic(cap<0>)
causes it to spit out the corresponding captured variable, that is a
. The actual behaviour of the function is, of course, still accessible with a normal call to magic(123)
.
As a bonus, the outer lambda is mutable
, and the capture accessors return by reference: you actually have read-write access to the captured variables!
You can observe and interact with this creature in its natural habitat on Coliru right here.