【问题标题】:C++ How to convert variadic arguments to Class member functionC ++如何将可变参数转换为类成员函数
【发布时间】:2021-08-10 08:54:07
【问题描述】:

我想创建一个类似 setInterval(func, delay, [arg1, arg2, ...]); 的 JavaScript 函数。

void func(int t) {
    std::cout<<t<<std::endl;
}

void func(int i, char* t) {
    std::cout<<t<<std::endl;
}

class Timer {
public:
    void setInterval(auto function, int interval, ...args);
};

void Timer::setInterval(auto function, int interval, ...args) {
    while(1) {
        function(args);
        msleep(interval);
    }
}

int main() {
    Timer *t1 = new Timer;
    t1->setInterval(func, 1000, 2021);

    Timer *t2 = new Timer;
    t2->setInterval(func, 1000, 2, "hello");

    while (1) {

    }
    return 0;
}

但我不知道如何将可变参数转换为类成员函数。谁能帮我?谢谢。

【问题讨论】:

  • 你知道如何为非成员函数做吗?如果是,问题究竟出在哪里?显示的代码中没有尝试正确使用可变参数
  • 另一个问题是func是一个重载的函数,所以你不能把它的地址换成auto
  • 你可以使用'stdarg'。 stackoverflow.com/a/1579732/8875520
  • while (1) {} 是 UB。

标签: c++


【解决方案1】:

你可以使用模板来做到这一点。

#include <iostream>
#include <thread>

class Timer 
{
public:
    template <typename T>
    void SetInterval(int interval, T t)
    {
        std::cout << t << std::endl;
        std::this_thread::sleep_for(std::chrono::milliseconds(interval));
    }

    template <typename T, typename... Types>
    void SetInterval(int interval, T t, Types... args)
    {
        SetInterval(interval, args...);
    }
};

int main() {
    Timer *t1 = new Timer;
    t1->SetInterval(1000, 2001);

    Timer *t2 = new Timer;
    t2->SetInterval(1000, 2, "hello");

    delete t1;
    delete t2;

    while (1) {

    }
    return 0;
}

【讨论】:

  • 更好(编译时)避免递归并使用折叠表达式:(std::cout &lt;&lt; args), ...); std::cout &lt;&lt; std::endl; /*..*/
  • 不行,只有args的最后一个参数,sleep才有效。
  • 我知道折叠表达式可以从 C++17 开始,我使用的是 c+11,并且,ssroreo 的代码中的第二次调用,只打印最后一个参数。
  • 在 C++11 中有一些技巧可以模仿折叠表达式(如 const int dummy[] = {0, (f(ts), 0)...};)。
  • 不确定是否只打印最后一个参数不是 OP 的错字 ;-)
【解决方案2】:

我建议

class Timer
{
public:

    void setInterval(std::function<void()> f, std::chrono::milliseconds interval)
    // template <typename F> void setInterval(F f, std::chrono::milliseconds interval)
    {
        while (true) {
            f();
            std::this_threas::sleep_for(interval);
        }
    }
};

调用类似于:

using namespace std::chrono_literals;

Timer t1;
t1.setInterval([](){ func(2021);}, 1000ms);

Timer().setInterval([](){ func(2, "hello");}, 1000ms);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-11-22
    • 1970-01-01
    • 2017-03-30
    • 1970-01-01
    • 1970-01-01
    • 2019-05-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多