使用成员函数创建 std::function 不编译
Creating std::function with a member function does not compile
我遇到了 C++ 的编译问题 class。
我的代码在这里:
#include <chrono>
#include <cstdint>
#include <thread>
#include <functional>
class Monitors {
public:
Monitors(std::uint32_t timeout1, std::uint32_t timeout2) : timeout_1(timeout1), timeout_2(timeout2) {
timer_start(task_1, timeout1); //does not compile
timer_start(&Monitors::task_2, timeout2); //does not compile either
}
private:
void timer_start( std::function<void(void)>& func, std::uint32_t interval) {
std::thread([func, interval]() {
while (true) {
func();
std::this_thread::sleep_for(std::chrono::milliseconds(interval)); }
}).detach();
}
void task_1() {
}
void task_2() {
}
private:
std::uint32_t timeout_1;
std::uint32_t timeout_2;
};
错误是:
non const lvalue to type std::function cannot bind to a temporary of
type void
有什么问题?我该如何解决?
编译器需要将成员函数转换为 std::function<void()>
对象以匹配 timer_start
函数参数列表。
这个对象是一个临时对象,一旦调用 timer_start
完成,它的生命周期就会结束。并且临时对象不能绑定到非常量引用(这就是错误消息所说的)。
简单的解决方案是 按值 传递函数。
void timer_start( std::function<void(void)> func, uint32_t interval)
第二个问题是,对于成员函数,您总是需要使用寻址运算符来获取指向它的指针。而且您始终还需要指定 class。
这意味着你需要做
timer_start(&Monitors::task_1, timeout1);
timer_start(&Monitors::task_2, timeout2);
最后是第三个问题:非静态成员函数比较特殊,需要调用对象。该对象成为函数内部的 this
指针。
调用该函数的对象通常作为隐藏的第一个参数传递,但是当使用例如std::function
我们需要明确指定该参数。
所以最后的声明需要
void timer_start( std::function<void(Monitors*)> func, uint32_t interval)
这最后一件事也意味着您需要将指向对象的指针传递给函数,在您的情况下您可以传递 this
:
// Capture this
// vvvv
std::thread([this, func, interval]() {
while (true) {
auto x = std::chrono::steady_clock::now() + std::chrono::milliseconds(interval);
func(this);
// ^^^^
// Pass this as argument
std::this_thread::sleep_until(x);
}
}).detach();
我遇到了 C++ 的编译问题 class。
我的代码在这里:
#include <chrono>
#include <cstdint>
#include <thread>
#include <functional>
class Monitors {
public:
Monitors(std::uint32_t timeout1, std::uint32_t timeout2) : timeout_1(timeout1), timeout_2(timeout2) {
timer_start(task_1, timeout1); //does not compile
timer_start(&Monitors::task_2, timeout2); //does not compile either
}
private:
void timer_start( std::function<void(void)>& func, std::uint32_t interval) {
std::thread([func, interval]() {
while (true) {
func();
std::this_thread::sleep_for(std::chrono::milliseconds(interval)); }
}).detach();
}
void task_1() {
}
void task_2() {
}
private:
std::uint32_t timeout_1;
std::uint32_t timeout_2;
};
错误是:
non const lvalue to type std::function cannot bind to a temporary of type void
有什么问题?我该如何解决?
编译器需要将成员函数转换为 std::function<void()>
对象以匹配 timer_start
函数参数列表。
这个对象是一个临时对象,一旦调用 timer_start
完成,它的生命周期就会结束。并且临时对象不能绑定到非常量引用(这就是错误消息所说的)。
简单的解决方案是 按值 传递函数。
void timer_start( std::function<void(void)> func, uint32_t interval)
第二个问题是,对于成员函数,您总是需要使用寻址运算符来获取指向它的指针。而且您始终还需要指定 class。
这意味着你需要做
timer_start(&Monitors::task_1, timeout1);
timer_start(&Monitors::task_2, timeout2);
最后是第三个问题:非静态成员函数比较特殊,需要调用对象。该对象成为函数内部的 this
指针。
调用该函数的对象通常作为隐藏的第一个参数传递,但是当使用例如std::function
我们需要明确指定该参数。
所以最后的声明需要
void timer_start( std::function<void(Monitors*)> func, uint32_t interval)
这最后一件事也意味着您需要将指向对象的指针传递给函数,在您的情况下您可以传递 this
:
// Capture this
// vvvv
std::thread([this, func, interval]() {
while (true) {
auto x = std::chrono::steady_clock::now() + std::chrono::milliseconds(interval);
func(this);
// ^^^^
// Pass this as argument
std::this_thread::sleep_until(x);
}
}).detach();