mercredi 28 octobre 2015

Apple Clang: can't compile call to std::erase for vector with custom allocator

I have the following snippet of code:

#include <algorithm>
#include <memory>
#include <vector>

// Example allocator, doesn't do anything but implements std::allocator_traits
template<typename T>
struct null_allocator {
  using value_type = T;
  using size_type = std::size_t;
  using pointer = T *;
  using const_pointer = const pointer;
  //using difference_type = typename std::pointer_traits<pointer>::difference_type;
  using reference = T &;
  using const_reference = const T &;

  null_allocator() {}

  template<typename U>
  null_allocator(const null_allocator<U>&) {}

  T* allocate(std::size_t size) {
    (void) size;
    return nullptr;
  }

  void deallocate(T* ptr, std::size_t size) {
    (void) ptr;
    (void) size;
  }

  template<typename U>
  struct rebind
  {
    typedef null_allocator<U> other;
  };
};

int main(int argc, char** argv) {
  std::vector<void*, null_allocator<void*>> vec;

  void * args;
  vec.push_back(args);
  vec.erase(vec.begin());
}

gcc.godbolt.org shows that it compiles with Clang: http://goo.gl/VhKLCe

I pass a custom allocator to a std::vector, push a single object onto the vector, and try to call std::erase on that vector. The custom allocator is a null allocator that does nothing and is unimportant. The point is that this snippet compiles fine on Linux with both GCC and Clang, but fails to compile on OSX with Xcode/Apple Clang.

The output of clang --version is Apple LLVM version 7.0.0 (clang-700.1.76).

It appears that the compiler cannot complete std::iterator_traits:

In file included from /Library/Developer/CommandLineTools/usr/bin/../include/c++/v1/memory:604:
/Library/Developer/CommandLineTools/usr/bin/../include/c++/v1/iterator:1120:54: error: no type named 'iterator_category' in
      'std::__1::iterator_traits<void **const>'
    typedef typename iterator_traits<iterator_type>::iterator_category iterator_category;
            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~
bug.cpp:42:13: note: in instantiation of template class 'std::__1::__wrap_iter<void **const>' requested here
  vec.erase(vec.begin());
            ^
In file included from bug.cpp:1:
In file included from /Library/Developer/CommandLineTools/usr/bin/../include/c++/v1/memory:604:
/Library/Developer/CommandLineTools/usr/bin/../include/c++/v1/iterator:1121:54: error: no type named 'value_type' in
      'std::__1::iterator_traits<void **const>'
    typedef typename iterator_traits<iterator_type>::value_type        value_type;
            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~
/Library/Developer/CommandLineTools/usr/bin/../include/c++/v1/iterator:1122:54: error: no type named 'difference_type' in
      'std::__1::iterator_traits<void **const>'
    typedef typename iterator_traits<iterator_type>::difference_type   difference_type;
            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~
/Library/Developer/CommandLineTools/usr/bin/../include/c++/v1/iterator:1123:54: error: no type named 'pointer' in
      'std::__1::iterator_traits<void **const>'
    typedef typename iterator_traits<iterator_type>::pointer           pointer;
            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~
/Library/Developer/CommandLineTools/usr/bin/../include/c++/v1/iterator:1124:54: error: no type named 'reference' in
      'std::__1::iterator_traits<void **const>'
    typedef typename iterator_traits<iterator_type>::reference         reference;

Does anyone know a good workaround for this issue?

Aucun commentaire:

Enregistrer un commentaire