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 的叮当声)。
我有以下代码片段:
#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 的叮当声)。