2

Fedora のデフォルトの C++ 標準ライブラリ (4.6.2) で clang を使用して小さな C++ プログラムをコンパイルしようとしています。Clang自体は問題なくコンパイルされ、テストプログラムのみを使用してコンパイルおよび実行されます。

私の他のプログラムは、clang が不平を言うロープを使用しています。

/usr/lib/gcc/x86_64-redhat-linux/4.6.2/../../../../include/c++/4.6.2/ext/ropeimpl.h:433:2: エラー: 使用未宣言の識別子 '_Data_allocate' _Data_allocate(_S_rounded_up_size(__old_len + __len));

このエラー メッセージについては、clang に対してバグが報告されており、clang は正しく、ライブラリ コードが無効であるという解決策がとられました。

Clangはここで正しいです。_Data_allocate の呼び出しには型依存の引数がないため、テンプレートの定義時に名前の検索が失敗します。

失敗したコードのコンテキスト:

  // Concatenate a C string onto a leaf rope by copying the rope data.
  // Used for short ropes.
  template <class _CharT, class _Alloc>
    typename rope<_CharT, _Alloc>::_RopeLeaf*
    rope<_CharT, _Alloc>::
    _S_leaf_concat_char_iter(_RopeLeaf* __r, const _CharT* __iter, size_t __len)
    {
      size_t __old_len = __r->_M_size;
      _CharT* __new_data = (_CharT*)
    _Data_allocate(_S_rounded_up_size(__old_len + __len));
      _RopeLeaf* __result;

      uninitialized_copy_n(__r->_M_data, __old_len, __new_data);
      uninitialized_copy_n(__iter, __len, __new_data + __old_len);
      _S_cond_store_eos(__new_data[__old_len + __len]);
      __try
    {
      __result = _S_new_RopeLeaf(__new_data, __old_len + __len,
                     __r->_M_get_allocator());
    }
      __catch(...)
    {
      _RopeRep::__STL_FREE_STRING(__new_data, __old_len + __len,
                      __r->_M_get_allocator());
      __throw_exception_again;
    }
      return __result;
    }

私の質問は、このコードが有効でない場合、簡単な回避策はありますか? g++ はこれを正常にコンパイルします。

4

1 に答える 1

4

libstdc++ ソースを掘り下げると、メンバー関数の定義は、テンプレートの定義でのマクロ_Data_allocateの展開の結果のようです (テンプレートのインスタンス化がパブリックに拡張されていることに注意してください)。__ROPE_DEFINE_ALLOCS_Rope_baserope<_CharT, _Alloc>_Rope_base<_CharT, _Alloc>

さらに呼び出しを修飾してみてください_Data_allocate。それ以外の:

_Data_allocate(_S_rounded_up_size(__old_len + __len));

試す:

_Rope_base<_CharT, _Alloc>::_Data_allocate(_S_rounded_up_size(__old_len + __len));

または単に:

_Base::_Data_allocate(_S_rounded_up_size(__old_len + __len));

typedef _Rope_base<_CharT, _Alloc> _Base;の定義で保護されているためですrope<_CharT, _Alloc>

編集: Clang をローカルにインストールしていませんが、オンラインの Clang 3.0 コンパイラ デモでこれをテストしました。

この非常に簡素化されたバージョンは、Clang 3.0 でコンパイルできません (エラー: 宣言されていない識別子 '_Data_allocate' の使用):

#include <cstddef>
#include <memory>

template <typename _CharT, class _Alloc>
class _Rope_base : public _Alloc
{
public:
    typedef typename _Alloc::template rebind<_CharT>::other _DataAlloc;
    static _CharT * _Data_allocate(std::size_t __n) {
        return _DataAlloc().allocate(__n);
    }
};

template <typename _CharT, class _Alloc = std::allocator<_CharT> >
class rope : public _Rope_base<_CharT, _Alloc>
{
protected:
    typedef _Rope_base<_CharT, _Alloc> _Base;

public:
    rope()
    {
        _Data_allocate(0);
    }
};

int main()
{
    rope<char> r;
}

上記のいずれかの方法で呼び出しを修飾することにより_Data_allocate、Clang 3.0 はコンパイルに成功します。

于 2011-12-28T23:06:00.673 に答える