【问题标题】:std::map of string to boost::thread_specific_ptr字符串的 std::map 到 boost::thread_specific_ptr
【发布时间】:2013-01-12 17:32:38
【问题描述】:

为什么这个编译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

【问题讨论】:

    标签: c++ boost c++11 g++ std-pair


    【解决方案1】:

    thread_specific_ptr 声明这些成员,以使类不可复制(注意非 const 参数):

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

    在 C++03 中,std::pair 没有声明复制构造函数,因此如果程序需要,它会隐式生成。 std::pair&lt;X, thread_specific_ptr&gt; 是不可复制的,因为它的一个成员是不可复制的,所以如果使用隐式复制构造函数就会出错。

    在 C++11 中 std::pair 有一个复制构造函数,它是显式默认的。它有签名:

    pair(const pair&) = default;
    

    编译器错误告诉您隐式生成的复制构造函数将具有此签名,因为thread_specific_ptr 复制构造函数签名采用非常量引用:

    pair(pair&) = default;
    

    由于默认构造函数与隐式声明的签名不同,因此复制构造函数格式错误。

    因此,在这两种情况下,pair&lt;X, thread_specific_ptr&gt; 都不可复制,但在 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;
    

    【讨论】:

    • 有趣 - 我看到 thread_specific_ptr 继承自 boost::noncopyable 在 boost 1.34 中,但不是在 1.52 中?
    【解决方案2】:

    Boost::thread-specific_ptr 类在某些 boost 版本中是不可复制的,这意味着 it can't be used in c++03 STL containers。我想这就是问题的根源,为什么更改 c++0x 标志可以解决问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-01-14
      • 2017-01-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多