Apple Clang: невозможно скомпилировать вызов std :: erase для вектора с настраиваемым распределителем

У меня есть следующий фрагмент кода:

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

Кто-нибудь знает хорошее решение этой проблемы?


person Jackie    schedule 28.10.2015    source источник
comment
Я не уверен насчет точной проблемы, но когда я использую libc ++ вместо libstdc ++, я получаю ту же ошибку в godbolt: goo.gl / EqjjtV   -  person Florian    schedule 29.10.2015


Ответы (1)


Я не знаю, почему это работает, но если вы измените using const_pointer = const pointer; в своем пользовательском распределителе на using const_pointer = const T *;, это, похоже, сработает для меня (даже в OS X с использованием Apple Clang).

person wjwwood    schedule 28.10.2015
comment
Конечно! using const_pointer = const pointer равно void * const, который является постоянным указателем и не совсем подходит в качестве итератора. - person Florian; 29.10.2015