Here is a SSCCE:
#include <memory>
#include <vector>
template <class T> struct my_allocator : std::allocator<T> {
//This overriding struct causes the error
template <class U> struct rebind {
typedef my_allocator<T> other;
};
//Ignore all this.
typedef std::allocator<T> base;
typename base::pointer allocate(typename base::size_type n, std::allocator<void>::const_pointer /*hint*/=nullptr) { return (T*)malloc(sizeof(T)*n); }
void deallocate(typename base::pointer p, typename base::size_type /*n*/) { free(p); }
};
int main(int /*argc*/, char* /*argv*/[]) {
std::vector<int,my_allocator<int>> vec;
return 0;
}
GCC likes it.
ICC likes it.
Clang likes it.
Even MSVC 2013 likes it.
But MSVC 2015 RC spits out:
1>------ Build started: Project: Test Alloc, Configuration: Debug Win32 ------
1> main.cpp
1>c:\program files (x86)\microsoft visual studio 14.0\vc\include\vector(579): error C2664: 'void std::_Wrap_alloc<my_allocator<int>>::deallocate(int *,unsigned int)': cannot convert argument 1 from 'std::_Container_proxy *' to 'int *'
1> c:\program files (x86)\microsoft visual studio 14.0\vc\include\vector(579): note: Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
1> c:\program files (x86)\microsoft visual studio 14.0\vc\include\vector(574): note: while compiling class template member function 'void std::_Vector_alloc<std::_Vec_base_types<_Ty,_Alloc>>::_Free_proxy(void)'
1> with
1> [
1> _Ty=int,
1> _Alloc=my_allocator<int>
1> ]
1> c:\program files (x86)\microsoft visual studio 14.0\vc\include\vector(541): note: see reference to function template instantiation 'void std::_Vector_alloc<std::_Vec_base_types<_Ty,_Alloc>>::_Free_proxy(void)' being compiled
1> with
1> [
1> _Ty=int,
1> _Alloc=my_allocator<int>
1> ]
1> c:\program files (x86)\microsoft visual studio 14.0\vc\include\vector(668): note: see reference to class template instantiation 'std::_Vector_alloc<std::_Vec_base_types<_Ty,_Alloc>>' being compiled
1> with
1> [
1> _Ty=int,
1> _Alloc=my_allocator<int>
1> ]
1> c:\users\ian mallett\desktop\test-alloc\main.cpp(18): note: see reference to class template instantiation 'std::vector<int,my_allocator<int>>' being compiled
Related program give similarly fishy sounding errors. Here are two:
error C2664: 'void std::_Wrap_alloc>::deallocate(int *,unsigned int)': cannot convert argument 1 from 'std::_Container_proxy *' to 'int *'
cannot convert argument 1 from 'std::_Wrap_alloc>' to 'const aligned_allocator &'
Boolean question: is this a bug? Iff it is, I will (try) to submit it.
[EDIT: as noted in the comments, this only occurs in debug mode. In release mode, it compiles and executes fine.] [EDIT: much simpler example]
Boolean question: is this a bug?
false
.
Although the template error given by MSVC here is surpassingly unhelpful, the error here is mine (reassuring since this version of the standard library is shipping today).
I created this allocator (and later, the reduced test case) from a variety of sources, which is why I assumed it was correct. However, as suggested in the comments, I checked again, this time exhaustively against the documentation.
The missing component here is one of the copy constructors (the template one that can't be auto-generated). This only shows up when the rebind
struct is defined since the rebind
struct overrides the same struct in the parent class (which, since it's in the parent class, ultimately causes the parent's copy constructor to be called, so there's no problem (except that it's technically wrong)).
The interesting thing here is that the error didn't occur until now. As I said, GCC, Clang, and MSVC 2013 all like it (even with their respective debug modes). It's just that none of these happened to call the template copy constructor. Nevertheless, it is specified by the standard, so again, the error is ultimately mine.
Congratulations to the MSVC compiler team, and sorry for the noise! :D
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With