为何tbb::enumerable_thread_specific不支持构造函数带非const引用的类型?
使用
tbb::enumerable_thread_specific处理构造函数带非const引用类型的问题 问题场景
尝试用tbb::enumerable_thread_specific为构造函数依赖非const引用的类型创建线程本地存储时,直接传递引用参数会触发编译错误,只有通过std::ref包装参数才能正常运行。
示例代码
#include <tbb/enumerable_thread_specific.h> struct A { A(int &) {} }; int main() { int i; // 正常运行 tbb::enumerable_thread_specific<A> ets1(std::ref(i)); // 编译报错 tbb::enumerable_thread_specific<A> ets(i); }
编译报错信息
In file included from /opt/compiler-explorer/libs/tbb/2021.4.0/include/tbb/enumerable_thread_specific.h:17, from <source>:1: /opt/compiler-explorer/libs/tbb/2021.4.0/include/oneapi/tbb/enumerable_thread_specific.h: In instantiation of 'void tbb::detail::d1::construct_by_args<T, P>::construct(void*) [with T = A; P = {int&}]': /opt/compiler-explorer/libs/tbb/2021.4.0/include/oneapi/tbb/enumerable_thread_specific.h:685:31: required from 'void tbb::detail::d1::callback_leaf<Constructor>::construct(void*) [with Constructor = tbb::detail::d1::construct_by_args<A, int&>]' /opt/compiler-explorer/libs/tbb/2021.4.0/include/oneapi/tbb/enumerable_thread_specific.h:684:10: required from here /opt/compiler-explorer/libs/tbb/2021.4.0/include/oneapi/tbb/enumerable_thread_specific.h:648:12: error: binding reference of type 'int&' to 'const std::decay<int&>::type' {aka 'const int'} discards qualifiers 648 | new(where) T(args...); | ^~~~~~~~~~~~~~~~~~~~~ <source>:4:7: note: initializing argument 1 of 'A::A(int&)' 4 | A(int &) {} | ^~~~~
原因分析
这是TBB的有意设计决策,并非实现bug。
TBB的enumerable_thread_specific在存储用于构造对象的参数时,为了保证线程安全和参数生命周期的稳定性,内部会对传入的参数执行std::decay处理,并以const限定的形式保存。当直接传递非const引用时,std::decay<int&>的结果是int,结合const限定后就变成了const int,无法匹配A的非const引用构造函数,因此触发编译错误。
而使用std::ref包装参数后,参数会被转换成std::reference_wrapper<int>类型,std::decay处理后仍然保留该类型,在构造A时会自动解引用为int&,刚好匹配构造函数的要求,因此可以正常运行。
内容的提问来源于stack exchange,提问作者Fedor
相关产品推荐
相关产品推荐

