字符串到boost::thread_specific_ptr的std::map

3
为什么这段代码无法在g++4.6和g++4.7上编译通过? 我正在尝试将字符串映射到线程本地存储。 我相信之前在boost 1.48中已经有类似的工作代码了。 实际上,这与boost的版本无关,而是取决于标志“-std=c++0x”是否存在。 如果没有该标志,代码可以编译通过。因此,请寻找错误的解释以及如何解决它的方法。
谢谢。
#include <map>
#include <boost/thread/tss.hpp>
#include <boost/shared_ptr.hpp>

int main(int argc, char** argv) {
  typedef boost::thread_specific_ptr< int > Tss_int_ptr;
  typedef std::map< std::string, Tss_int_ptr > Tss_int_map_t;
  Tss_int_map_t tmap;
  return 0;
}

错误信息如下。
g++-4.7 -g -std=c++0x -I"/home/someone/open_source/admin/install/boost_1_52_0/include" -c  ~/tmp/fail.cpp
In file included from /usr/include/c++/4.7/bits/stl_algobase.h:65:0,
             from /usr/include/c++/4.7/bits/stl_tree.h:63,
             from /usr/include/c++/4.7/map:60,
             from /home/someone/tmp/fail.cpp:1:
/usr/include/c++/4.7/bits/stl_pair.h: In instantiation of ‘struct std::pair<const std::basic_string<char>, boost::thread_specific_ptr<int> >’:
/usr/include/c++/4.7/bits/stl_tree.h:133:12:   required from ‘struct std::_Rb_tree_node<std::pair<const std::basic_string<char>, boost::thread_specific_ptr<int> > >’
/usr/include/c++/4.7/bits/stl_tree.h:1082:4:   required from ‘void std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_erase(std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Link_type) [with _Key = std::basic_string<char>; _Val = std::pair<const std::basic_string<char>, boost::thread_specific_ptr<int> >; _KeyOfValue = std::_Select1st<std::pair<const std::basic_string<char>, boost::thread_specific_ptr<int> > >; _Compare = std::less<std::basic_string<char> >; _Alloc = std::allocator<std::pair<const std::basic_string<char>, boost::thread_specific_ptr<int> > >; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Link_type = std::_Rb_tree_node<std::pair<const std::basic_string<char>, boost::thread_specific_ptr<int> > >*]’
/usr/include/c++/4.7/bits/stl_tree.h:646:9:   required from ‘std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::~_Rb_tree() [with _Key = std::basic_string<char>; _Val = std::pair<const std::basic_string<char>, boost::thread_specific_ptr<int> >; _KeyOfValue = std::_Select1st<std::pair<const std::basic_string<char>, boost::thread_specific_ptr<int> > >; _Compare = std::less<std::basic_string<char> >; _Alloc = std::allocator<std::pair<const std::basic_string<char>, boost::thread_specific_ptr<int> > >]’
/usr/include/c++/4.7/bits/stl_map.h:90:11:   required from here
/usr/include/c++/4.7/bits/stl_pair.h:119:17: error: ‘constexpr std::pair<_T1, _T2>::pair(const std::pair<_T1, _T2>&) [with _T1 = const std::basic_string<char>; _T2 = boost::thread_specific_ptr<int>; std::pair<_T1, _T2> = std::pair<const std::basic_string<char>, boost::thread_specific_ptr<int> >]’ declared to take const reference, but implicit declaration would take non-const
2个回答

5

thread_specific_ptr声明了以下成员,以使该类不可复制(请注意非const参数):

private:
    thread_specific_ptr(thread_specific_ptr&);
    thread_specific_ptr& operator=(thread_specific_ptr&);

在C++03中,std::pair没有声明复制构造函数,因此如果程序需要,则会隐式生成。由于std::pair<X, thread_specific_ptr>的一个成员不可复制,所以它不可复制。如果使用了隐式复制构造函数,则会出错。
在C++11中,std::pair有一个显式默认的复制构造函数。其签名为:
pair(const pair&) = default;

编译器错误告诉您,由于“thread_specific_ptr”的复制构造函数签名采用非const引用,隐式生成的复制构造函数将具有此签名。
pair(pair&) = default;

因为默认构造函数的签名与隐式声明的不同,所以复制构造函数是不合法的。
因此,在两种情况下,pair<X, thread_specific_ptr> 都不可复制,但在C++11中,即使您不尝试复制对象,也会更早地注意到这个错误。
如果 boost::thread_specific_ptr 使用普通的 C++11 惯用语,将类设置为不可复制,则代码可以正常工作:
thread_specific_ptr(const thread_specific_ptr&) = delete;
thread_specific_ptr& operator=(const thread_specific_ptr&) = delete;

我建议你向Boost报告此问题。在C++11模式下,复制操作应该被删除。

作为一种解决方法,您可以将该类型包装在自己的类型中,并删除复制操作,然后使用该类型:

template<typename T>
struct TSS : boost::thread_specific_ptr<T>
{
  TSS() = default;
  TSS(void (*f)(T*)) : boost::thread_specific_ptr<T>(f) { }
  TSS(const TSS&) = delete;
  TSS& operator=(const TSS&) = delete;
};

现在你可以使用这个代码并编译它:
typedef TSS< int > Tss_int_ptr;

有趣的是,我看到在boost 1.34中,thread_specific_ptr继承自boost :: noncopyable,但在1.52中却没有? - Roddy

2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接