如何为含std::any与std::function成员的类实现移动构造函数
问题:vxWorks下PosixTimer移动构造函数导致std::function/std::any异常
运行环境
- 操作系统:vxWorks
- C标准:C17
- 编译器:Clang 16
问题描述
在为自定义PosixTimer类实现移动构造函数时,遇到两个异常问题:
- 处理
std::function<void(const std::any&)>类型成员时,目标对象无有效值,调用时抛出std::bad_function_call异常; - 处理
std::any类型成员时,调用std::any_cast会抛出std::bad_any_cast异常。
已尝试的实现
std::function相关尝试
this->callback = source.callback; this->callback.swap(source.callback); this->callback = std::move(source.callback);
std::any相关尝试
this->callback_data = source.callback_data; this->callback_data.swap(source.callback_data);
完整代码
posix_timer.hpp
#include <any> #include <map> #include <ctime> #include <string> #include <csignal> #include <cstdint> #include <functional> typedef int signal_t; class PosixTimer { public: static inline const int signal_rt_min = SIGRTMIN, signal_rt_max = SIGRTMAX; using callback_timer_t = std::function<void(const std::any&)>; PosixTimer(callback_timer_t callback, const std::any& callback_data, bool periodic = false) : PosixTimer(periodic) { this->callback = callback; this->callback_data = callback_data; } PosixTimer(){} PosixTimer(const PosixTimer& instance);//; = delete; //Delete copy constructor PosixTimer& operator=(const PosixTimer& instance);// = delete; //Delete Copy Assignment PosixTimer(PosixTimer&& source); PosixTimer& operator=(PosixTimer&& source); ~PosixTimer(); void registerCallback(callback_timer_t callback, const std::any& callback_data); private: static inline std::map<signal_t, bool> signal_usage_status; signal_t signal_id; static inline std::uint8_t total_timer_count = 0; std::uint8_t timer_count = 0; bool periodic; std::uint64_t timeout;// in nano-seconds timer_t timer_id; sigset_t mask; std::any callback_data; struct sigevent sev; struct sigaction sa; struct itimerspec its; bool timer_valid {false}; static void handler(int sig, siginfo_t *si, void *uc); callback_timer_t callback; };
posix_timer.cpp
PosixTimer::PosixTimer(PosixTimer &&source) { std::cout << "Inside Move Constructor PosixTimer::PosixTimer(PosixTimer &&source)\n"; this->timer_id = source.timer_id; this->timer_valid = source.timer_valid; this->signal_id = source.signal_id; this->timer_count = source.timer_count; this->periodic = source.periodic; this->timeout = source.timeout;// in nano-seconds this->mask = source.mask; //this->callback_data = source.callback_data; this->callback_data.swap(source.callback_data); this->sev = source.sev; this->sa = source.sa; this->its = source.its; // this->callback = source.callback; // this->callback.swap(source.callback); this->callback = std::move(source.callback); //Reset source timer_id to 0 and timer validity (timer_valid) to false source.timer_id = 0; source.timer_valid = false; } PosixTimer &PosixTimer::operator=(PosixTimer &&source) { std::cout << "Inside Move Assignment PosixTimer &PosixTimer::operator=(PosixTimer &&source)\n"; if (this != &source) //performs no operation if you try to assign the object to itself { this->timer_id = source.timer_id; this->timer_valid = source.timer_valid; this->signal_id = source.signal_id; this->timer_count = source.timer_count; this->periodic = source.periodic; this->timeout = source.timeout;// in nano-seconds this->mask = source.mask; // this->callback_data = source.callback_data; this->callback_data.swap(source.callback_data); this->sev = source.sev; this->sa = source.sa; this->its = source.its; // this->callback = source.callback; // this->callback.swap(source.callback); this->callback = std::move(source.callback); //Reset source timer_id to 0 and timer validity (timer_valid) to false source.timer_id = 0; source.timer_valid = false; } return *this; } void PosixTimer::registerCallback(callback_timer_t callback, std::any callback_data) { try { this->callback_data = callback_data; this->callback = callback; } catch(const std::exception& e) { std::cerr << "PosixTimer::registerCallback(callback_timer_t callback, const std::any& callback_data) : " << e.what() << std::endl; } }
main.cpp
#include "posix_timer.hpp" #include <iostream> #include <vector> #include <any> void handler(const std::any& data) { try { std::cout << "Data Type : " << data.type().name() << std::endl; std::cout << "Signal Handler called. Time Delay : " << std::any_cast<int>(data) << std::endl; } catch(const std::exception& e) { std::cerr << "Main::handler : " << e.what() << '\n'; } } int main(int argc, char const *argv[]) { // std::any data = std::make_any<int>(10); std::vector<PosixTimer> vt; PosixTimer::initialize(); { PosixTimer t; bool return_status = t.create(PosixTimer::in_seconds(10), true); t.registerCallback(handler, 10); vt.push_back(std::move(t)); } while (true) { sleep(25); //vt.at(0).registerCallback(handler, 5); vt.at(0).update(PosixTimer::in_seconds(5)); } return 0; }
运行输出
Inside constructor PosixTimer::PosixTimer() PosixTimer::create(std::uint64_t timeout, bool periodic) called PosixTimer::create(void) called Signal ID : 34 TIMER START CALLED, Timer ID : 0 Timer Value Sec: 10 nsec: 0 Timer Interval Value Sec: 10 nsec: 0 PosixTimer::registerCallback Callback Data : 10 Inside destructor PosixTimer::~PosixTimer() timer->callback is empty terminate called after throwing an instance of 'std::bad_function_call' what(): bad_function_call Aborted
内容的提问来源于stack exchange,提问作者Dark Sorrow
相关产品推荐
相关产品推荐

