此 C++ 模板代码有效吗?G++编译它,但Clang不会

Is this c++ template code valid? g++ compiles it but clang won't

本文关键字:编译 不会 Clang G++ C++ 代码 有效      更新时间:2023-10-16

我正在尝试用Fedora上的默认c++标准库(4.6.2)使用clang编译一个小的c++程序。Clang本身可以很好地编译,测试程序也可以很好地编译和运行。

我的另一个程序使用了clang抱怨的rope。

/usr/lib/gcc/x86_64-redhat-linux/4.6.2/../../../../包括/c++/4.6.2/ext/ropeimpl.h: 433:2:错误:使用未声明的标识符'_Data_allocate'_Data_allocate (_S_rounded_up_size (__old_len + __len));

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;
    }

我的问题是,如果这个代码是无效的,是否有一个简单的解决方案?c++可以编译这个。

从libstdc++源代码中可以看出,成员函数_Data_allocate的定义是在模板_Rope_base的定义中扩展了__ROPE_DEFINE_ALLOCS宏(注意,模板实例化rope<_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));

因为rope<_CharT, _Alloc>的定义中保护了typedef _Rope_base<_CharT, _Alloc> _Base;

EDIT:我没有在本地安装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成功地编译了它。

相关文章: