3

g++4.6 と g++4.7 のコンパイルに失敗するのはなぜですか? 文字列からスレッド固有のストレージへのマッピングを取得しようとしています。ブースト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
4

2 に答える 2

5

thread_specific_ptrクラスをコピー不可にするために、これらのメンバーを宣言します (非 const パラメーターに注意してください)。

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

C++03std::pairではコピー コンストラクターが宣言されていないため、プログラムで必要に応じて暗黙的に生成されます。A のstd::pair<X, thread_specific_ptr>メンバーの 1 つがコピー可能でないため、 A はコピー可能ではありません。そのため、暗黙のコピー コンストラクターが使用された場合はエラーになります。

C++11std::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;
于 2013-01-13T20:17:03.467 に答える
2

Boost::thread-specific_ptrclass は一部のブースト バージョンではコピーできません。つまり、c++03 STL コンテナーでは使用できません。それが問題の根本であり、c++0x フラグを変更すると問題が解決する理由だと思います。

于 2013-01-12T20:52:27.163 に答える