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

I am trying to compile a small c++ program using clang with the default C++ standard library(4.6.2) on Fedora. Clang itself compiles okay and a test program using only compiles and runs fine.

My other program uses ropes which clang complains about.

/usr/lib/gcc/x86_64-redhat-linux/4.6.2/../../../../include/c++/4.6.2/ext/ropeimpl.h:433:2: error: use of undeclared identifier '_Data_allocate' _Data_allocate(_S_rounded_up_size(__old_len + __len));

A bug was filed against clang for this error message and the resolution was clang is correct, the library code is invalid.

Clang is correct here. There are no type-dependent arguments in the call to _Data_allocate, so name lookup fails at template definition time.

The context for the failing code:

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

My question is, if this code is not valid, is there an easy workaround? g++ compiles this okay.


Digging through the libstdc++ source, it appears that the definition of member function _Data_allocate results from an expansion of the __ROPE_DEFINE_ALLOCS macro in the definition of template _Rope_base (note that template instantiation rope<_CharT, _Alloc> publicly extends _Rope_base<_CharT, _Alloc> ).

You could try qualifying the call to _Data_allocate further. Instead of:

_Data_allocate(_S_rounded_up_size(__old_len + __len));

Try:

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

Or simply:

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

because of the protected typedef _Rope_base<_CharT, _Alloc> _Base; in the definition of rope<_CharT, _Alloc> .

EDIT: I don't have Clang installed locally, but I tested this out with the online Clang 3.0 compiler demo.

This highly pared-down version fails to compile with Clang 3.0 (error: use of undeclared identifier '_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;
}

By qualifying the call to _Data_allocate in either way suggested above, Clang 3.0 succeeds in compiling it.

链接地址: http://www.djcxy.com/p/15142.html

上一篇: 为什么clang ++在Mavericks下无法在Mac上编译,除了使用sudo?

下一篇: 这个C ++模板代码是否有效? g ++编译它,但clang不会