一个干净的方式来存储一个函数及其(任意类型,任意数)参数 [英] A clean way to store a function and its (arbitrary-type, arbitrary-number) arguments

查看:238
本文介绍了一个干净的方式来存储一个函数及其(任意类型,任意数)参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对于库,我想要一个函数接受另一个函数及其参数,然后将它们全部存储以供稍后调用。参数必须允许任何类型的混合,但函数只需要返回void。这样的东西:

For a library, I'd like a function to accept another function and its arguments, then store them all for calling later. The arguments must allow for any mixture of types, but the functions only need to return void. Something like this:

void myFunc1(int arg1, float arg2);
void myFunc2(const char *arg1);
class DelayedCaller
{ ...
public:
    static DelayedCaller *setup(Function func, …);
};

...
DelayedCaller* caller1 = DelayedCaller::setup(&myFunc1, 123, 45.6);
DelayedCaller* caller2 = DelayedCaller::setup(&myFunc2, "A string");

caller1->call(); // Calls myFunc1(), with arguments 123 and 45.6
caller2->call(); // Calls myFunc2(), with argument "A string"

一种方法是让DelayedCaller :: setup()接受std ::函数,并让我的库用户在调用setup()之前使用std :: bind()。

One approach is to make DelayedCaller::setup() accept a std::function, and have my library users use std::bind() prior to calling setup(). However, is there a way to implement setup() such that users don't need to do the binding themselves?

编辑:DelayedCaller是一个用于实现绑定的方法,一个现有的类。

Edit: DelayedCaller is an existing class. setup() is a new static method I'd like to add.

推荐答案

一个可能性是使用可变参数模板并调用< a href =http://en.cppreference.com/w/cpp/utility/functional/bind =nofollow> std :: bind() setup()函数中:

An possibility is to use variadic templates and call std::bind() from within the setup() function:

#include <iostream>
#include <string>
#include <functional>
#include <memory>

void myFunc1(int arg1, float arg2)
{
    std::cout << arg1 << ", " << arg2 << '\n';
}
void myFunc2(const char *arg1)
{
    std::cout << arg1 << '\n';
}

class DelayedCaller
{
public:
    template <typename TFunction, typename... TArgs>
    static std::unique_ptr<DelayedCaller> setup(TFunction&& a_func,
                                                TArgs&&... a_args)
    {
        return std::unique_ptr<DelayedCaller>(new DelayedCaller(
            std::bind(std::forward<TFunction>(a_func),
                      std::forward<TArgs>(a_args)...)));
    }
    void call() const { func_(); }

private:
    using func_type = std::function<void()>;
    DelayedCaller(func_type&& a_ft) : func_(std::forward<func_type>(a_ft)) {}
    func_type func_;
};

int main()
{
    auto caller1(DelayedCaller::setup(&myFunc1, 123, 45.6));
    auto caller2(DelayedCaller::setup(&myFunc2, "A string"));

    caller1->call();
    caller2->call();

    return 0;
}

输出:


123, 45.6
A string

返回智能指针,例如 std :: unique_ptr ,而不是返回一个原始指针(或通过值返回和避免动态分配。 func_type 是可移动的,如果参数是可移动的,或者可能是相当便宜的复制反正你可能需要定义移动构造函数和移动赋值运算符,它们是在特定条件下生成的)。

Return a smart pointer, such as std::unique_ptr, instead of returning a raw pointer (or return by value and avoid dynamic allocation. The func_type is moveable if the arguments are moveable, or it may be quite cheap to copy anyway. You may need to define the move constructor and move assignment operator, they are generated under certain conditions).

这篇关于一个干净的方式来存储一个函数及其(任意类型,任意数)参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆