【问题标题】:Encapsulating arguments of variadic function in a class instance在类实例中封装可变参数函数的参数
【发布时间】:2020-05-29 16:44:45
【问题描述】:
这里有一些有漏洞的代码:
template<typename... Args>
class A
{
typedef function_type = void(*)(Args...);
public:
void set_args(Args&& ... args)
{
// something magic manages to encapsulate
// args in instance of A
}
void apply_args(function_type function)
{
// something magic manages to "retrieve"
// the encapsulated args
function(std::forward<Args>(args)...);
}
};
这有可能吗?
【问题讨论】:
标签:
c++
parameter-passing
function-pointers
variadic-functions
【解决方案1】:
您可以使用std::tuple 和std::apply
#include <iostream>
#include <tuple>
#include <functional>
#include <string>
template <typename... Ts>
class A
{
private:
std::function<void (Ts...)> f;
std::tuple<Ts...> args;
public:
template <typename F>
A(F&& func, Ts&&... args)
: f(std::forward<F>(func)),
args(std::make_tuple(std::forward<Ts>(args)...))
{}
void Invoke()
{
std::apply(f, args);
}
};
template <typename F, typename... Args>
A<Args...> Create(F&& f, Args&&... args)
{
return A<Args...>(std::forward<F>(f), std::forward<Args>(args)...);
}
int main()
{
auto helloWorld = Create([] (std::string a, std::string b) { std::cout << a << ", " << b; }, std::string("Hello"), std::string("World!"));
helloWorld.Invoke();
}
【解决方案2】:
您可以将模板参数存储在 std::tuple 类型的类数据成员中,并使用 std::apply 以便将存储的参数应用于提供的函数。
所以,假设你有一个像这样的Action 类:
template <typename... Args>
class Action {
std::tuple<Args...> args_;
public:
Action() = default;
Action(Args&&... args)
: args_(std::forward<Args>(args)...)
{}
void args(Args&&... args) {
args_ = std::make_tuple<Args...>(std::forward<Args>(args)...);
}
template <typename F>
void apply(F&& fun) {
std::apply(std::forward<F&&>(fun), args_);
}
};
您通过构造函数Action action(1, 2, 3); 或通过单独的函数action.set(3, 2, 1); 设置参数。
那么你的 main 函数可以如下所示:
int main() {
Action action(1, 2);
action.apply([](int a, int b) {
std::cout << "a + b = " << (a + b) << std::endl;
});
return 0;
}
查看live example