Reputation: 167
I'm looking to write a class such than it can store a piece of data and pass it through a lambda. I'd also like to be able to have an option to not pass a value in the constructor and have the constructor generate with a lambda without a parameter. I'm OK, with still having a piece of data on the class.
I've tried using optionals and using a default template parameter of type void but couldn't get it to work. The closest thing I got was this.
template<class T = void>
class X {
std::optional<T> d; // data present or garbage data
std::function<void(T)> f; // parameter = type of data or void if no arg provided
public:
X(std::optional<T> a, std::function<void(T)> b) : d{a}, f{b} {}
a() {
if (d.has_value()) f(d);
else f();
}
}
Hoping the constructor work like
X(5, [&](int x) {}); // where the int type is implied from the constructor
OR
X([&](){}); // where the lack of parameter implies the function parameter is void
Thank you.
EDIT: provided an example of an attempt to generate the class myself EDIT 2: attempted to clarified the need to store and call the function at a later date.
Upvotes: 2
Views: 265
Reputation: 12263
You can use something like this:
#include <iostream>
#include <functional>
void foo() {
std::cout << "void foo()" << std::endl;
}
void bar(int x) {
std::cout << "void foo(int x) with parameter x = " << x << std::endl;
}
class X {
public:
template <typename F, typename ... Args>
X(F&& f, Args&&... args) {
std::invoke(std::forward<F>(f), std::forward<Args>(args)...);
}
};
int main() {
X a(foo);
X b(bar, 1);
X c([&](int x, int y) {
std::cout << "lambda with parameters x = " << x << " y = " << y << std::endl;
}, 1, 2);
return 0;
}
Check live
Basically, by using provided class X
you can send whatever function you want (free function, lambda, etc.) and pass any number of parameters you want.
UPDATE
According to the OP's comment and wish to store the lambda and arguments to a class member and call it later, here is the updated code:
#include <iostream>
#include <tuple>
#include <functional>
template <typename F, typename ... Args>
class X {
public:
X(F&& f, Args&&... args)
: f_(std::forward<F>(f)),
args_(std::forward<Args>(args)...)
{}
void call() {
std::apply(f_, args_);
}
private:
F f_;
std::tuple<Args...> args_;
};
int main() {
X c([&](int x, int y) {
std::cout << "lambda with parameters x = " << x << " y = " << y << std::endl;
}, 1, 2);
c.call();
return 0;
}
Check live
Upvotes: 3