C++11:使用 auto/decltype/result_of使代码可读易维护

本文深入探讨了C++11中自动类型推导的原理与应用,包括auto、decltype和result_of的使用场景与优势。通过具体实例展示了如何简化变量定义和使用时的类型冗余,提高代码的可读性和通用性。同时,文章还对比了C++与动态语言在类型推导上的差异,强调了自动类型推导在保持类型安全的同时提高编程效率的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

http://blog.youkuaiyun.com/anzhsoft/article/details/17507085


C++11 终于加入了自动类型推导。以前,我们不得不使用Boost的相关组件来实现,现在,我们可以使用“原生态”的自动类型推导了!

C++引入自动的类型推导,并不是在向动态语言(强类型语言又称静态类型语言,是指需要进行变量/对象类型声明的语言,一般情况下需要编译执行。例如C/C++/Java;弱类型语言又称动态类型语言,是指不需要进行变量/对象类型声明的语言,一般情况下不需要编译(但也有编译型的)。例如PHP/ASP/Ruby/Python/Perl/ABAP/SQL/JavaScript/Unix Shell等等)靠拢,通过弱化类型实现编程的灵活性;而是在保持类型安全的前提下提高代码的可读性,易用性和通用性。要理解这点就必须对C++泛型编程(GP)和为什么要泛型有一定认识,推荐阅读:刘未鹏:泛型编程:源起、实现与意义。类型自动推导带来的最大好处就是拥有初始化表达式的负责类型声明简化了。很多时候,名字空间,模版成了类型的一部分,经常要写很长的表达式,不小心写错了,编译器就给爆出一堆近似与乱码的错误信息,调试起来更是头疼。

1) auto

简单用法:

  1. map< int, map<int,int> > m;  
  2. // C++98/03 style:  
  3. map<int, map<int,int> >::const_iterator it = m.begin();  
  4. // C++11 style  
  5. const auto it = m.begin();   
其实,我们只需要知道it是迭代器就行,通过它可以访问容器的元素。而且如果要修改m的类型,那么导致大量的迭代器都要修改,违反了DRY(Don't Repeat Yourself,不要重复粘帖你的代码)原则。即使使用typedef,也不能完全避免这个问题。所以,任何人都应该使用auto!(注:auto的语义已经更改,C++98/03是修饰自动存储期的局部变量。但是实际上这个关键字几乎没有人用,因为一般函数内没有声明为static的变量都是自动存储期的局部变量)

本文讲详细讨论auto/decltype/result_of 用法及应用场景。

auto并不是说这个变量的类型不定,或者在运行时再确定,而是说这个变量在编译时可以由编译器推导出来,使用auto和decltype只是占位符的作用,告诉编译器这个变量的类型需要编译器推导,借以消除C++变量定义和使用时的类型冗余,从而解放了程序员打更多无意义的字符,避免了手动推导某个变量的类型,甚至有时候需要很多额外的开销才能绕过的类型声明。

但是,auto不能解决精度问题:

  1. auto a = numeric_limits<unsinged int>::max();  
  2. auto b = 1;  
  3. auto c = a + b;// c is also unsigned int, and it is 0 since it has overflowed.  
这并不像一些动态语言那样,会自动扩展c以存储更大的值。因此这点要注意。

auto的使用细则:

  1. int x;  
  2. int *ptr = &y;  
  3. double foo();  
  4. int &bar();  
  5.   
  6. auto *a = &x; // int *  
  7. auto &b = x; // int &  
  8. auto c = ptr; //int *  
  9. auto &d = ptr; // int *  
  10. auto *e = &foo(); // compiler error, the pointer cannot point to a temporary variable.  
  11. auto &f = foo(); // compiler error  
  12. auto g = bar(); // int  
  13. auto &h = bar(); // int &  
变量a, c , d都是指针,且都指向x,实际上对于a,c,d三个变量而言,声明其为auto *或者auto并没有区别。但是,如果变量要是另外一个变量的引用,则必须使用auto &,注意g和h的区别。

auto和const,volatile和存在这一定的关系。C++将volatile和const成为cv-qualifier。鉴于cv限制符的特殊性,C++11标准规定auto可以和cv-qualifier一切使用,但是auto声明的变量并不能从其初始化表达式中带走cv-qualifier。还是通过实例理解吧:

  1. double x;  
  2. float * bar();  
  3.   
  4. const auto a = foo(); // const double  
  5. const auto &b = x; // const double &  
  6. volatile auto *c = bar(); // volatile float *  
  7.   
  8. auto d = a; // double  
  9. auto &e = a; // const double &  
  10. auto f = c; // float *  
  11. volatile auto &g = c; // volatile float * &  
注意auto声明的变量d,f都无法带走a 和f的const和volatile。但是例外是引用和指针,声明的变量e和g都保持了其引用对象相同的属性。

2) decltype

decltype主要为库作者所用,但是如果是我们需要用template,那么使用它也能简洁我们的代码。

与C完全不支持动态类型的是,C++在C++98标准中就部分支持动态类型了:RTTI(RunTime Type Identification)。RTTI就是为每个类型产生一个type_info的数据,我们可以使用typeid(var)来获取一个变量的type_info。type_info::name就是类型的名字;type_info::hash_code()是C++11中新增的,返回该类型唯一的hash值。

在decltype产生之前,很多编译器厂商都有自己的类型推导的扩展,比如GCC的typeof操作符。

言归正传,decltype就是不用计算表达式就可以推导出表达式所得值的类型。

  1. template<typename T1, typename T2>  
  2. void sum(T1 &t1, T2 &t2, decltype(t1 + t2) &s){  
  3.   s = t1 + t2;  
  4. }  
  5.   
  6. // another scenario  
  7.   
  8. template<typename T1, typename T2>  
  9. auto sum(T1 &t1, T2 &t2) ->decltype(t1 + t2)){  
  10.   return t1 + t2;  
  11. }  
很容易看出与auto的不同。实例化模版的时候,decltype也可以有用武之地:
  1. int hash(char *);  
  2.   
  3. map<char *, decltype(hash(nullptr))> m;// map<char *, int> m may be more simple, but when hash value changed to other type, such as   
  4. //string, it would cause a lot of maintenance effort.   

接下来看一个更复杂的例子。首先定义Person:
  1. struct Person  
  2. {  
  3.   string name;  
  4.   int age;  
  5.   string city;  
  6. };  

我们想得到一系列的multimap,可以按照city,age进行分组。
第一个版本:
  1. template<typename T, typename Fn>  
  2. multimap<T, Person> GroupBy(const vector<Person>& vt, const Fn& keySlector)  
  3. {  
  4.   multimap<T, Person> map;  
  5.   std::for_each(vt.begin(), vt.end(), [&map](const Person& person)  
  6.   {  
  7.     map.insert(make_pair(keySlector(person), person)); //keySlector返回值就是键值,通过keySelector擦除了类型  
  8.   });  
  9.   
  10. return map;  
  11. }  

通过传入key type,和获取相应值的函数(可以使用lambda),就可以获取这个multimap。但是,实际上key type就是Fn的返回值,可以不用传入:通过keySlector(person)进行判断。这里就要说说如何获取闭包的返回值类型了。获取闭包的返回值类型的方法有三种:

  1.     通过decltype
  2.     通过declval
  3.     通过result_of


第一种方式,通过decltype:

multimap<decltype(keySlector((Person&)nulltype)), Person>或者multimap<decltype(keySlector(*((Person*)0))), Person>
这种方式可以解决问题,但不够好,因为它有两个magic number:nulltype和0。
通过declval:
multimap<decltype(declval(Fn)(declval(Person))), Person>
这种方式用到了declval,declval的强大之处在于它能获取任何类型的右值引用,而不管它是不是有默认构造函数,因此我们通过declval(Fn)获得了function的右值引用,然后再调用形参declval(Person)的右值引用,需要注意的是declval获取的右值引用不能用于求值,因此我们需要用decltype来推断出最终的返回值。这种方式比刚才那种方式要好一点,因为消除了魔法数,但是感觉稍微有点麻烦,写的代码有点繁琐,有更好的方式吗?看第三种方式吧:

通过result_of
multimap<typename std::result_of<Fn(Person)>::type, Person>
std::result_of<Fn(Arg)>::type可以获取function的返回值,没有魔法数,也没有declval繁琐的写法,很优雅。其实,查看源码就知道result_of内部就是通过declval实现的,作法和方式二一样,只是简化了写法。

最终版本:

  1. vector<Person> v = { {"aa", 20, "shanghai"}, { "bb", 25, "beijing" }, { "cc", 25, "nanjing" }, { "dd", 20, "nanjing" } };  
  2. typedef typename vector<Persion>::value_type value_type;  
  3. template<typename Fn>  
  4. multimap<typename result_of<Fn(value_type)>::type, value_type> groupby(const vector<value_type> &v, const Fn& f)  // -> decltype(f(*((value_type*)0))),f((value_type&)nullptr)  
  5. {  
  6. //typedef typename result_of<Fn(value_type)>::type ketype;  
  7.   typedef  decltype(declval<Fn>()(declval <value_type>())) ketype;  
  8.   
  9.   multimap<ketype, value_type> mymap;  
  10.   std::for_each(begin(v), end(v), [&mymap, &f](value_type item)  
  11.   {  
  12.     mymap.insert(make_pair(f(item), item));  
  13.   });  
  14.   return mymap;  
  15. }  

看一下最终的调用情况:
  1. vector<Person> v = { {"aa", 20, "shanghai"}, { "bb", 25, "beijing" }, { "cc", 25, "nanjing" }, { "dd", 20, "nanjing" } };  
  2. // group by age  
  3. auto r1 = range.groupby([](const Person& person){return person.age; });  
  4. // group by name  
  5. auto r2 = range.groupby([](const Person& person){return person.name; });  
  6. // group by city  
  7. auto r3 = range.groupby([](const Person& person){return person.city; });  

result_of 其实就是通过decltype来推导函数的返回类型。result_of的一种可能的实现如下:
  1. template<class F, class... ArgTypes>  
  2. struct result_of<F(ArgTypes...)>  
  3. {  
  4.   typedef decltype(  
  5.                   declval<F>()(declval<ArgTypes>()...)  
  6.                   ) type;  
  7. }  

另外一个使用result_of的例子:
  1. templateclass Obj >  
  2. class CalculusVer2 {  
  3. public:  
  4.     template<class Arg>  
  5.     typename std::result_of<Obj(Arg)>::type operator()(Arg& a) const  
  6.     {   
  7.         return member(a);  
  8.     }  
  9. private:  
  10.     Obj member;  
  11. };  

总结:

auto适用于任何人,除非需要类型转换,否则你应该使用它

decltype适合推导表达式,因此在库中大量使用,当然它也可以推导函数的返回值,但是函数的返回值的推导,还是交给result_of吧!

引用:

http://www.cnblogs.com/qicosmos/p/3286057.html
#include "../include/include/realtime_utils/realtime_utils.hpp" #include <rclcpp/rclcpp.hpp> #include <std_msgs/msg/float64.hpp> #include <chrono> #include <thread> #include <vector> #include <string> #include <memory> #include <atomic> #include <limits> using namespace std::chrono_literals; // 原子操作辅助工具 namespace atomic_utils { template<typename T> void atomic_update_max(std::atomic<T>& atomic_var, T value) { T current = atomic_var.load(); while (value > current && !atomic_var.compare_exchange_weak(current, value)) {} } template<typename T> void atomic_update_min(std::atomic<T>& atomic_var, T value) { T current = atomic_var.load(); while (value < current && !atomic_var.compare_exchange_weak(current, value)) {} } } // 多线程订阅者节点 class MultiThreadSubscriber : public rclcpp::Node { public: // 线程统计结构(全原子操作) struct ThreadStats { std::atomic<uint64_t> message_count{0}; std::atomic<uint64_t> total_latency{0}; // 改为uint64避免溢出 std::atomic<int64_t> max_latency{0}; std::atomic<int64_t> min_latency{std::numeric_limits<int64_t>::max()}; // 原子重置方法 void reset() { message_count = 0; total_latency = 0; max_latency = 0; min_latency = std::numeric_limits<int64_t>::max(); } }; // 消息数据结构 struct MessageData { double value; std::chrono::steady_clock::time_point receive_time; int thread_id; }; // 构造函数 MultiThreadSubscriber() : Node("multithread_subscriber") { // 参数声明 declare_parameter("thread_count", 4); declare_parameter("process_time_us", 200); // 获取参数 int thread_count = get_parameter("thread_count").as_int(); int process_time = get_parameter("process_time_us").as_int(); thread_stats_.resize(thread_count); // 创建订阅线程 for (int i = 0; i < thread_count; ++i) { threads_.emplace_back(&MultiThreadSubscriber::subscriber_loop, this, i, process_time); } // 创建低优先级监控线程 monitor_thread_ = std::thread([this]() { pthread_setname_np(pthread_self(), "monitor_thread"); realtime_utils::RTThread::set_current_thread_priority(SCHED_OTHER, 0); monitor_loop(); }); } // 析构函数 ~MultiThreadSubscriber() { running_ = false; for (auto& thread : threads_) { if (thread.joinable()) thread.join(); } if (monitor_thread_.joinable()) monitor_thread_.join(); } private: // 订阅线程主循环 void subscriber_loop(int thread_id, int process_time) { // 设置高实时优先级 std::string thread_name = "sub_thread_" + std::to_string(thread_id); pthread_setname_np(pthread_self(), thread_name.c_str()); if (!realtime_utils::RTThread::set_current_thread_priority( SCHED_FIFO, 90 - thread_id)) { // 提高优先级 RCLCPP_ERROR(get_logger(), "Thread %d failed to set real-time priority", thread_id); } // 创建专属话题 auto topic_name = "control_topic_" + std::to_string(thread_id); auto qos = rclcpp::QoS(100).reliable().durability_volatile(); // 增加队列大小 // 创建订阅器 auto sub = create_subscription<std_msgs::msg::Float64>( topic_name, qos, [this, thread_id](const std_msgs::msg::Float64::SharedPtr msg) { MessageData data; data.value = msg->data; data.receive_time = std::chrono::steady_clock::now(); data.thread_id = thread_id; if (!message_buffer_.push(data)) { RCLCPP_WARN_THROTTLE(get_logger(), *get_clock(), 1000, "Thread %d buffer full, message dropped", thread_id); } }); // 主处理循环 while (rclcpp::ok() && running_) { MessageData data; if (message_buffer_.pop(data)) { // 模拟处理耗时 std::this_thread::sleep_for(std::chrono::microseconds(process_time)); // 计算端到端延迟 auto latency = std::chrono::duration_cast<std::chrono::microseconds>( std::chrono::steady_clock::now() - data.receive_time).count(); // 无锁更新统计 update_thread_stats(data.thread_id, latency); } else { std::this_thread::sleep_for(100us); // 更短的休眠 } } } // 无锁统计更新 void update_thread_stats(size_t thread_id, int64_t latency) { if (thread_id >= thread_stats_.size()) return; auto& stats = thread_stats_[thread_id]; stats.message_count++; stats.total_latency += latency; atomic_utils::atomic_update_max(stats.max_latency, latency); atomic_utils::atomic_update_min(stats.min_latency, latency); } // 监控循环(无锁) void monitor_loop() { auto last_print = std::chrono::steady_clock::now(); while (rclcpp::ok() && running_) { std::this_thread::sleep_for(5s); // 降低输出频率 // 原子获取统计快照 std::vector<ThreadStats> snapshot; for (auto& stats : thread_stats_) { ThreadStats s; s.message_count = stats.message_count.exchange(0); s.total_latency = stats.total_latency.exchange(0); s.max_latency = stats.max_latency.exchange(0); s.min_latency = stats.min_latency.exchange(std::numeric_limits<int64_t>::max()); snapshot.push_back(s); } // 输出统计(非实时上下文) print_stats(snapshot); } } // 打印统计(无锁) void print_stats(const std::vector<ThreadStats>& snapshot) { RCLCPP_INFO(get_logger(), "\n=== Subscriber Threads Stats ==="); for (size_t i = 0; i < snapshot.size(); ++i) { const auto& stats = snapshot[i]; if (stats.message_count == 0) continue; double avg_latency = static_cast<double>(stats.total_latency) / stats.message_count; RCLCPP_INFO(get_logger(), "Thread %zu: %lu msgs | Avg: %.2f us | Max: %ld us | Min: %ld us", i, stats.message_count.load(), avg_latency, stats.max_latency.load(), stats.min_latency.load()); } } // 成员变量 std::vector<std::thread> threads_; std::thread monitor_thread_; std::atomic<bool> running_{true}; realtime_utils::LockFreeRingBuffer<MessageData, 20000> message_buffer_; // 增大缓冲区 std::vector<ThreadStats> thread_stats_; // 无锁统计 }; int main(int argc, char** argv) { rclcpp::init(argc, argv); auto node = std::make_shared<MultiThreadSubscriber>(); rclcpp::spin(node); rclcpp::shutdown(); return 0; } #include "../include/include/realtime_utils/realtime_utils.hpp" #include <rclcpp/rclcpp.hpp> #include <std_msgs/msg/float64.hpp> #include <chrono> #include <thread> #include <vector> #include <string> #include <memory> #include <atomic> #include <limits> using namespace std::chrono_literals; // 原子操作辅助工具 namespace atomic_utils { template<typename T> void atomic_update_max(std::atomic<T>& atomic_var, T value) { T current = atomic_var.load(); while (value > current && !atomic_var.compare_exchange_weak(current, value)) {} } template<typename T> void atomic_update_min(std::atomic<T>& atomic_var, T value) { T current = atomic_var.load(); while (value < current && !atomic_var.compare_exchange_weak(current, value)) {} } } // 多线程发布者节点 class MultiThreadPublisher : public rclcpp::Node { public: // 线程统计结构(全原子操作) struct ThreadStats { std::atomic<uint64_t> message_count{0}; std::atomic<uint64_t> total_latency{0}; // 改为uint64避免溢出 std::atomic<int64_t> max_latency{0}; std::atomic<int64_t> min_latency{std::numeric_limits<int64_t>::max()}; // 原子重置方法 void reset() { message_count = 0; total_latency = 0; max_latency = 0; min_latency = std::numeric_limits<int64_t>::max(); } }; // 构造函数 MultiThreadPublisher() : Node("multithread_publisher") { // 参数声明 declare_parameter("thread_count", 4); declare_parameter("frequency", 500.0); // 获取参数 int thread_count = get_parameter("thread_count").as_int(); double frequency = get_parameter("frequency").as_double(); thread_stats_.resize(thread_count); // 初始化统计容器 // 创建发布线程 for (int i = 0; i < thread_count; ++i) { threads_.emplace_back(&MultiThreadPublisher::publisher_loop, this, i, frequency); } // 创建低优先级监控线程 monitor_thread_ = std::thread([this]() { pthread_setname_np(pthread_self(), "monitor_thread"); realtime_utils::RTThread::set_current_thread_priority(SCHED_OTHER, 0); monitor_loop(); }); } // 析构函数 ~MultiThreadPublisher() { running_ = false; for (auto& thread : threads_) { if (thread.joinable()) thread.join(); } if (monitor_thread_.joinable()) monitor_thread_.join(); } private: // 发布线程主循环 void publisher_loop(int thread_id, double frequency) { // 设置线程名和实时优先级 std::string thread_name = "pub_thread_" + std::to_string(thread_id); pthread_setname_np(pthread_self(), thread_name.c_str()); if (!realtime_utils::RTThread::set_current_thread_priority( SCHED_FIFO, 90 - thread_id)) { // 提高优先级 RCLCPP_ERROR(get_logger(), "Thread %d failed to set real-time priority", thread_id); } // 创建专属话题和发布器 auto topic_name = "control_topic_" + std::to_string(thread_id); auto qos = rclcpp::QoS(100).reliable().durability_volatile(); // 增加队列大小 auto pub = create_publisher<std_msgs::msg::Float64>(topic_name, qos); // 计算发布周期 const auto period = std::chrono::nanoseconds(static_cast<int64_t>(1e9 / frequency)); auto start_time = std::chrono::steady_clock::now(); uint64_t count = 0; // 复用消息对象 auto msg = std::make_shared<std_msgs::msg::Float64>(); msg->data = thread_id; while (rclcpp::ok() && running_) { auto next_time = start_time + count * period; std::this_thread::sleep_until(next_time); msg->data = count; pub->publish(*msg); auto latency = std::chrono::duration_cast<std::chrono::microseconds>( std::chrono::steady_clock::now() - next_time).count(); // 无锁更新统计 update_thread_stats(thread_id, latency); count++; } } // 无锁统计更新 void update_thread_stats(size_t thread_id, int64_t latency) { if (thread_id >= thread_stats_.size()) return; auto& stats = thread_stats_[thread_id]; stats.message_count++; stats.total_latency += latency; atomic_utils::atomic_update_max(stats.max_latency, latency); atomic_utils::atomic_update_min(stats.min_latency, latency); } // 监控循环(无锁) void monitor_loop() { auto last_print = std::chrono::steady_clock::now(); while (rclcpp::ok() && running_) { std::this_thread::sleep_for(5s); // 降低输出频率 // 原子获取统计快照 std::vector<ThreadStats> snapshot; for (auto& stats : thread_stats_) { ThreadStats s; s.message_count = stats.message_count.exchange(0); s.total_latency = stats.total_latency.exchange(0); s.max_latency = stats.max_latency.exchange(0); s.min_latency = stats.min_latency.exchange(std::numeric_limits<int64_t>::max()); snapshot.push_back(s); } // 输出统计(非实时上下文) print_stats(snapshot); } } // 打印统计(无锁) void print_stats(const std::vector<ThreadStats>& snapshot) { RCLCPP_INFO(get_logger(), "\n=== Publisher Threads Stats ==="); for (size_t i = 0; i < snapshot.size(); ++i) { const auto& stats = snapshot[i]; if (stats.message_count == 0) continue; double avg_latency = static_cast<double>(stats.total_latency) / stats.message_count; RCLCPP_INFO(get_logger(), "Thread %zu: %lu msgs | Avg: %.2f us | Max: %ld us | Min: %ld us", i, stats.message_count.load(), avg_latency, stats.max_latency.load(), stats.min_latency.load()); } } // 成员变量 std::vector<std::thread> threads_; std::thread monitor_thread_; std::atomic<bool> running_{true}; std::vector<ThreadStats> thread_stats_; // 无锁统计 }; int main(int argc, char** argv) { rclcpp::init(argc, argv); if (getuid() != 0) { RCLCPP_ERROR(rclcpp::get_logger("main"), "This program requires root privileges for real-time scheduling"); return 1; } auto node = std::make_shared<MultiThreadPublisher>(); rclcpp::spin(node); rclcpp::shutdown(); return 0; } 报错: --- stderr: realtime_demo /home/yidds/YiDDS/multithreading_YIDDS/src/realtime_demo/src/multithread_subscriber.cpp: In member function ‘void MultiThreadSubscriber::monitor_loop()’: /home/yidds/YiDDS/multithreading_YIDDS/src/realtime_demo/src/multithread_subscriber.cpp:154:14: warning: variable ‘last_print’ set but not used [-Wunused-but-set-variable] 154 | auto last_print = std::chrono::steady_clock::now(); | ^~~~~~~~~~ /home/yidds/YiDDS/multithreading_YIDDS/src/realtime_demo/src/multithread_publisher.cpp: In member function ‘void MultiThreadPublisher::monitor_loop()’: /home/yidds/YiDDS/multithreading_YIDDS/src/realtime_demo/src/multithread_publisher.cpp:140:14: warning: variable ‘last_print’ set but not used [-Wunused-but-set-variable] 140 | auto last_print = std::chrono::steady_clock::now(); | ^~~~~~~~~~ In file included from /usr/include/x86_64-linux-gnu/c++/11/bits/c++allocator.h:33, from /usr/include/c++/11/bits/allocator.h:46, from /usr/include/c++/11/memory:64, from /home/yidds/YiDDS/YiDDS_humble/install/rclcpp/include/rclcpp/rclcpp/rclcpp.hpp:153, from /home/yidds/YiDDS/multithreading_YIDDS/src/realtime_demo/src/../include/include/realtime_utils/realtime_utils.hpp:3, from /home/yidds/YiDDS/multithreading_YIDDS/src/realtime_demo/src/multithread_subscriber.cpp:1: /usr/include/c++/11/ext/new_allocator.h: In instantiation of ‘void __gnu_cxx::new_allocator<_Tp>::construct(_Up*, _Args&& ...) [with _Up = MultiThreadSubscriber::ThreadStats; _Args = {const MultiThreadSubscriber::ThreadStats&}; _Tp = MultiThreadSubscriber::ThreadStats]’: /usr/include/c++/11/bits/alloc_traits.h:516:17: required from ‘static void std::allocator_traits<std::allocator<_Tp1> >::construct(std::allocator_traits<std::allocator<_Tp1> >::allocator_type&, _Up*, _Args&& ...) [with _Up = MultiThreadSubscriber::ThreadStats; _Args = {const MultiThreadSubscriber::ThreadStats&}; _Tp = MultiThreadSubscriber::ThreadStats; std::allocator_traits<std::allocator<_Tp1> >::allocator_type = std::allocator<MultiThreadSubscriber::ThreadStats>]’ /usr/include/c++/11/bits/stl_vector.h:1192:30: required from ‘void std::vector<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = MultiThreadSubscriber::ThreadStats; _Alloc = std::allocator<MultiThreadSubscriber::ThreadStats>; std::vector<_Tp, _Alloc>::value_type = MultiThreadSubscriber::ThreadStats]’ /home/yidds/YiDDS/multithreading_YIDDS/src/realtime_demo/src/multithread_subscriber.cpp:167:35: required from here /usr/include/c++/11/ext/new_allocator.h:162:11: error: use of deleted function ‘MultiThreadSubscriber::ThreadStats::ThreadStats(const MultiThreadSubscriber::ThreadStats&)’ 162 | { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); } | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /home/yidds/YiDDS/multithreading_YIDDS/src/realtime_demo/src/multithread_subscriber.cpp:35:12: note: ‘MultiThreadSubscriber::ThreadStats::ThreadStats(const MultiThreadSubscriber::ThreadStats&)’ is implicitly deleted because the default definition would be ill-formed: 35 | struct ThreadStats { | ^~~~~~~~~~~ /home/yidds/YiDDS/multithreading_YIDDS/src/realtime_demo/src/multithread_subscriber.cpp:35:12: error: use of deleted function ‘std::atomic<long unsigned int>::atomic(const std::atomic<long unsigned int>&)’ In file included from /usr/include/c++/11/future:41, from /home/yidds/YiDDS/YiDDS_humble/install/rclcpp/include/rclcpp/rclcpp/executors.hpp:18, from /home/yidds/YiDDS/YiDDS_humble/install/rclcpp/include/rclcpp/rclcpp/rclcpp.hpp:155, from /home/yidds/YiDDS/multithreading_YIDDS/src/realtime_demo/src/../include/include/realtime_utils/realtime_utils.hpp:3, from /home/yidds/YiDDS/multithreading_YIDDS/src/realtime_demo/src/multithread_subscriber.cpp:1: /usr/include/c++/11/atomic:898:7: note: declared here 898 | atomic(const atomic&) = delete; | ^~~~~~ /home/yidds/YiDDS/multithreading_YIDDS/src/realtime_demo/src/multithread_subscriber.cpp:35:12: error: use of deleted function ‘std::atomic<long unsigned int>::atomic(const std::atomic<long unsigned int>&)’ 35 | struct ThreadStats { | ^~~~~~~~~~~ In file included from /usr/include/c++/11/future:41, from /home/yidds/YiDDS/YiDDS_humble/install/rclcpp/include/rclcpp/rclcpp/executors.hpp:18, from /home/yidds/YiDDS/YiDDS_humble/install/rclcpp/include/rclcpp/rclcpp/rclcpp.hpp:155, from /home/yidds/YiDDS/multithreading_YIDDS/src/realtime_demo/src/../include/include/realtime_utils/realtime_utils.hpp:3, from /home/yidds/YiDDS/multithreading_YIDDS/src/realtime_demo/src/multithread_subscriber.cpp:1: /usr/include/c++/11/atomic:898:7: note: declared here 898 | atomic(const atomic&) = delete; | ^~~~~~ /home/yidds/YiDDS/multithreading_YIDDS/src/realtime_demo/src/multithread_subscriber.cpp:35:12: error: use of deleted function ‘std::atomic<long int>::atomic(const std::atomic<long int>&)’ 35 | struct ThreadStats { | ^~~~~~~~~~~ In file included from /usr/include/c++/11/future:41, from /home/yidds/YiDDS/YiDDS_humble/install/rclcpp/include/rclcpp/rclcpp/executors.hpp:18, from /home/yidds/YiDDS/YiDDS_humble/install/rclcpp/include/rclcpp/rclcpp/rclcpp.hpp:155, from /home/yidds/YiDDS/multithreading_YIDDS/src/realtime_demo/src/../include/include/realtime_utils/realtime_utils.hpp:3, from /home/yidds/YiDDS/multithreading_YIDDS/src/realtime_demo/src/multithread_subscriber.cpp:1: /usr/include/c++/11/atomic:875:7: note: declared here 875 | atomic(const atomic&) = delete; | ^~~~~~ /home/yidds/YiDDS/multithreading_YIDDS/src/realtime_demo/src/multithread_subscriber.cpp:35:12: error: use of deleted function ‘std::atomic<long int>::atomic(const std::atomic<long int>&)’ 35 | struct ThreadStats { | ^~~~~~~~~~~ In file included from /usr/include/c++/11/future:41, from /home/yidds/YiDDS/YiDDS_humble/install/rclcpp/include/rclcpp/rclcpp/executors.hpp:18, from /home/yidds/YiDDS/YiDDS_humble/install/rclcpp/include/rclcpp/rclcpp/rclcpp.hpp:155, from /home/yidds/YiDDS/multithreading_YIDDS/src/realtime_demo/src/../include/include/realtime_utils/realtime_utils.hpp:3, from /home/yidds/YiDDS/multithreading_YIDDS/src/realtime_demo/src/multithread_subscriber.cpp:1: /usr/include/c++/11/atomic:875:7: note: declared here 875 | atomic(const atomic&) = delete; | ^~~~~~ In file included from /usr/include/x86_64-linux-gnu/c++/11/bits/c++allocator.h:33, from /usr/include/c++/11/bits/allocator.h:46, from /usr/include/c++/11/memory:64, from /home/yidds/YiDDS/YiDDS_humble/install/rclcpp/include/rclcpp/rclcpp/rclcpp.hpp:153, from /home/yidds/YiDDS/multithreading_YIDDS/src/realtime_demo/src/../include/include/realtime_utils/realtime_utils.hpp:3, from /home/yidds/YiDDS/multithreading_YIDDS/src/realtime_demo/src/multithread_publisher.cpp:1: /usr/include/c++/11/ext/new_allocator.h: In instantiation of ‘void __gnu_cxx::new_allocator<_Tp>::construct(_Up*, _Args&& ...) [with _Up = MultiThreadPublisher::ThreadStats; _Args = {const MultiThreadPublisher::ThreadStats&}; _Tp = MultiThreadPublisher::ThreadStats]’: /usr/include/c++/11/bits/alloc_traits.h:516:17: required from ‘static void std::allocator_traits<std::allocator<_Tp1> >::construct(std::allocator_traits<std::allocator<_Tp1> >::allocator_type&, _Up*, _Args&& ...) [with _Up = MultiThreadPublisher::ThreadStats; _Args = {const MultiThreadPublisher::ThreadStats&}; _Tp = MultiThreadPublisher::ThreadStats; std::allocator_traits<std::allocator<_Tp1> >::allocator_type = std::allocator<MultiThreadPublisher::ThreadStats>]’ /usr/include/c++/11/bits/stl_vector.h:1192:30: required from ‘void std::vector<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = MultiThreadPublisher::ThreadStats; _Alloc = std::allocator<MultiThreadPublisher::ThreadStats>; std::vector<_Tp, _Alloc>::value_type = MultiThreadPublisher::ThreadStats]’ /home/yidds/YiDDS/multithreading_YIDDS/src/realtime_demo/src/multithread_publisher.cpp:153:35: required from here /usr/include/c++/11/ext/new_allocator.h:162:11: error: use of deleted function ‘MultiThreadPublisher::ThreadStats::ThreadStats(const MultiThreadPublisher::ThreadStats&)’ 162 | { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); } | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /home/yidds/YiDDS/multithreading_YIDDS/src/realtime_demo/src/multithread_publisher.cpp:35:12: note: ‘MultiThreadPublisher::ThreadStats::ThreadStats(const MultiThreadPublisher::ThreadStats&)’ is implicitly deleted because the default definition would be ill-formed: 35 | struct ThreadStats { | ^~~~~~~~~~~ /home/yidds/YiDDS/multithreading_YIDDS/src/realtime_demo/src/multithread_publisher.cpp:35:12: error: use of deleted function ‘std::atomic<long unsigned int>::atomic(const std::atomic<long unsigned int>&)’ In file included from /usr/include/c++/11/future:41, from /home/yidds/YiDDS/YiDDS_humble/install/rclcpp/include/rclcpp/rclcpp/executors.hpp:18, from /home/yidds/YiDDS/YiDDS_humble/install/rclcpp/include/rclcpp/rclcpp/rclcpp.hpp:155, from /home/yidds/YiDDS/multithreading_YIDDS/src/realtime_demo/src/../include/include/realtime_utils/realtime_utils.hpp:3, from /home/yidds/YiDDS/multithreading_YIDDS/src/realtime_demo/src/multithread_publisher.cpp:1: /usr/include/c++/11/atomic:898:7: note: declared here 898 | atomic(const atomic&) = delete; | ^~~~~~ /home/yidds/YiDDS/multithreading_YIDDS/src/realtime_demo/src/multithread_publisher.cpp:35:12: error: use of deleted function ‘std::atomic<long unsigned int>::atomic(const std::atomic<long unsigned int>&)’ 35 | struct ThreadStats { | ^~~~~~~~~~~ In file included from /usr/include/c++/11/future:41, from /home/yidds/YiDDS/YiDDS_humble/install/rclcpp/include/rclcpp/rclcpp/executors.hpp:18, from /home/yidds/YiDDS/YiDDS_humble/install/rclcpp/include/rclcpp/rclcpp/rclcpp.hpp:155, from /home/yidds/YiDDS/multithreading_YIDDS/src/realtime_demo/src/../include/include/realtime_utils/realtime_utils.hpp:3, from /home/yidds/YiDDS/multithreading_YIDDS/src/realtime_demo/src/multithread_publisher.cpp:1: /usr/include/c++/11/atomic:898:7: note: declared here 898 | atomic(const atomic&) = delete; | ^~~~~~ /home/yidds/YiDDS/multithreading_YIDDS/src/realtime_demo/src/multithread_publisher.cpp:35:12: error: use of deleted function ‘std::atomic<long int>::atomic(const std::atomic<long int>&)’ 35 | struct ThreadStats { | ^~~~~~~~~~~ In file included from /usr/include/c++/11/future:41, from /home/yidds/YiDDS/YiDDS_humble/install/rclcpp/include/rclcpp/rclcpp/executors.hpp:18, from /home/yidds/YiDDS/YiDDS_humble/install/rclcpp/include/rclcpp/rclcpp/rclcpp.hpp:155, from /home/yidds/YiDDS/multithreading_YIDDS/src/realtime_demo/src/../include/include/realtime_utils/realtime_utils.hpp:3, from /home/yidds/YiDDS/multithreading_YIDDS/src/realtime_demo/src/multithread_publisher.cpp:1: /usr/include/c++/11/atomic:875:7: note: declared here 875 | atomic(const atomic&) = delete; | ^~~~~~ /home/yidds/YiDDS/multithreading_YIDDS/src/realtime_demo/src/multithread_publisher.cpp:35:12: error: use of deleted function ‘std::atomic<long int>::atomic(const std::atomic<long int>&)’ 35 | struct ThreadStats { | ^~~~~~~~~~~ In file included from /usr/include/c++/11/future:41, from /home/yidds/YiDDS/YiDDS_humble/install/rclcpp/include/rclcpp/rclcpp/executors.hpp:18, from /home/yidds/YiDDS/YiDDS_humble/install/rclcpp/include/rclcpp/rclcpp/rclcpp.hpp:155, from /home/yidds/YiDDS/multithreading_YIDDS/src/realtime_demo/src/../include/include/realtime_utils/realtime_utils.hpp:3, from /home/yidds/YiDDS/multithreading_YIDDS/src/realtime_demo/src/multithread_publisher.cpp:1: /usr/include/c++/11/atomic:875:7: note: declared here 875 | atomic(const atomic&) = delete; | ^~~~~~ In file included from /usr/include/c++/11/memory:66, from /home/yidds/YiDDS/YiDDS_humble/install/rclcpp/include/rclcpp/rclcpp/rclcpp.hpp:153, from /home/yidds/YiDDS/multithreading_YIDDS/src/realtime_demo/src/../include/include/realtime_utils/realtime_utils.hpp:3, from /home/yidds/YiDDS/multithreading_YIDDS/src/realtime_demo/src/multithread_publisher.cpp:1: /usr/include/c++/11/bits/stl_uninitialized.h: In instantiation of ‘_ForwardIterator std::uninitialized_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = std::move_iterator<MultiThreadPublisher::ThreadStats*>; _ForwardIterator = MultiThreadPublisher::ThreadStats*]’: /usr/include/c++/11/bits/stl_uninitialized.h:333:37: required from ‘_ForwardIterator std::__uninitialized_copy_a(_InputIterator, _InputIterator, _ForwardIterator, std::allocator<_Tp>&) [with _InputIterator = std::move_iterator<MultiThreadPublisher::ThreadStats*>; _ForwardIterator = MultiThreadPublisher::ThreadStats*; _Tp = MultiThreadPublisher::ThreadStats]’ /usr/include/c++/11/bits/stl_uninitialized.h:355:2: required from ‘_ForwardIterator std::__uninitialized_move_if_noexcept_a(_InputIterator, _InputIterator, _ForwardIterator, _Allocator&) [with _InputIterator = MultiThreadPublisher::ThreadStats*; _ForwardIterator = MultiThreadPublisher::ThreadStats*; _Allocator = std::allocator<MultiThreadPublisher::ThreadStats>]’ /usr/include/c++/11/bits/vector.tcc:659:48: required from ‘void std::vector<_Tp, _Alloc>::_M_default_append(std::vector<_Tp, _Alloc>::size_type) [with _Tp = MultiThreadPublisher::ThreadStats; _Alloc = std::allocator<MultiThreadPublisher::ThreadStats>; std::vector<_Tp, _Alloc>::size_type = long unsigned int]’ /usr/include/c++/11/bits/stl_vector.h:940:4: required from ‘void std::vector<_Tp, _Alloc>::resize(std::vector<_Tp, _Alloc>::size_type) [with _Tp = MultiThreadPublisher::ThreadStats; _Alloc = std::allocator<MultiThreadPublisher::ThreadStats>; std::vector<_Tp, _Alloc>::size_type = long unsigned int]’ /home/yidds/YiDDS/multithreading_YIDDS/src/realtime_demo/src/multithread_publisher.cpp:60:29: required from here /usr/include/c++/11/bits/stl_uninitialized.h:138:72: error: static assertion failed: result type must be constructible from value type of input range 138 | static_assert(is_constructible<_ValueType2, decltype(*__first)>::value, | ^~~~~ /usr/include/c++/11/bits/stl_uninitialized.h:138:72: note: ‘std::integral_constant<bool, false>::value’ evaluates to false In file included from /usr/include/c++/11/memory:66, from /home/yidds/YiDDS/YiDDS_humble/install/rclcpp/include/rclcpp/rclcpp/rclcpp.hpp:153, from /home/yidds/YiDDS/multithreading_YIDDS/src/realtime_demo/src/../include/include/realtime_utils/realtime_utils.hpp:3, from /home/yidds/YiDDS/multithreading_YIDDS/src/realtime_demo/src/multithread_subscriber.cpp:1: /usr/include/c++/11/bits/stl_uninitialized.h: In instantiation of ‘_ForwardIterator std::uninitialized_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = std::move_iterator<MultiThreadSubscriber::ThreadStats*>; _ForwardIterator = MultiThreadSubscriber::ThreadStats*]’: /usr/include/c++/11/bits/stl_uninitialized.h:333:37: required from ‘_ForwardIterator std::__uninitialized_copy_a(_InputIterator, _InputIterator, _ForwardIterator, std::allocator<_Tp>&) [with _InputIterator = std::move_iterator<MultiThreadSubscriber::ThreadStats*>; _ForwardIterator = MultiThreadSubscriber::ThreadStats*; _Tp = MultiThreadSubscriber::ThreadStats]’ /usr/include/c++/11/bits/stl_uninitialized.h:355:2: required from ‘_ForwardIterator std::__uninitialized_move_if_noexcept_a(_InputIterator, _InputIterator, _ForwardIterator, _Allocator&) [with _InputIterator = MultiThreadSubscriber::ThreadStats*; _ForwardIterator = MultiThreadSubscriber::ThreadStats*; _Allocator = std::allocator<MultiThreadSubscriber::ThreadStats>]’ /usr/include/c++/11/bits/vector.tcc:659:48: required from ‘void std::vector<_Tp, _Alloc>::_M_default_append(std::vector<_Tp, _Alloc>::size_type) [with _Tp = MultiThreadSubscriber::ThreadStats; _Alloc = std::allocator<MultiThreadSubscriber::ThreadStats>; std::vector<_Tp, _Alloc>::size_type = long unsigned int]’ /usr/include/c++/11/bits/stl_vector.h:940:4: required from ‘void std::vector<_Tp, _Alloc>::resize(std::vector<_Tp, _Alloc>::size_type) [with _Tp = MultiThreadSubscriber::ThreadStats; _Alloc = std::allocator<MultiThreadSubscriber::ThreadStats>; std::vector<_Tp, _Alloc>::size_type = long unsigned int]’ /home/yidds/YiDDS/multithreading_YIDDS/src/realtime_demo/src/multithread_subscriber.cpp:67:29: required from here /usr/include/c++/11/bits/stl_uninitialized.h:138:72: error: static assertion failed: result type must be constructible from value type of input range 138 | static_assert(is_constructible<_ValueType2, decltype(*__first)>::value, | ^~~~~ /usr/include/c++/11/bits/stl_uninitialized.h:138:72: note: ‘std::integral_constant<bool, false>::value’ evaluates to false 修改完给我完整的代码,要求功能基本不变,
最新发布
07-31
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值