Apple Clang:无法为带有自定义分配器的向量编译对 std::erase 的调用

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

我有以下代码片段:

#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 显示它使用 Clang 编译:http://goo.gl/VhKLCe

我将自定义分配器传递给 std::vector,将单个对象推送到向量上,然后尝试对该向量调用 std::erase。自定义分配器是一个空分配器,它什么也不做,也不重要。关键是这个片段在 Linux 上用 GCC 和 Clang 编译得很好,但是在 OSX 上用 Xcode/Apple Clang 编译失败。

clang --version 的输出是 Apple LLVM 版本 7.0.0 (clang-700.1.76)。

看来编译器无法完成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;

有人知道解决此问题的好方法吗?

我不知道为什么会这样,但是如果您将自定义分配器中的 using const_pointer = const pointer; 更改为 using const_pointer = const T *; 它似乎对我有用(即使在 OS X 上使用 Apple 的叮当声)。