I have the problem that GCC is complaining about a type mismatch when compiling the following code:
#include <iostream>
#include <cstdint>
#include <vector>
#include <limits>
template <class T>
struct Mallocator {
typedef T value_type;
Mallocator() = default;
template <class U>
Mallocator(const Mallocator<U>&) {}
T* allocate(std::size_t n) {
if (n > std::numeric_limits<std::size_t>::max() / sizeof(T))
throw "std::bad_array_new_length";
if (auto p = static_cast<T*>(malloc(n * sizeof(T)))) {
report(p, n);
return p;
}
throw std::bad_alloc();
}
void deallocate(T* p, std::size_t n) {
report(p, n, 0);
free(p);
}
private:
void report(T* p, std::size_t n, bool alloc = true) const {
std::cout << (alloc ? "Alloc: " : "Dealloc: ") << sizeof(T) * n
<< " bytes at " << std::hex << std::showbase
<< reinterpret_cast<void*>(p) << std::dec << '\n';
}
};
struct Foo
{
Foo(int f): m_values{f} {}
std::vector<int, Mallocator<int> > m_values;
std::vector<int>::iterator begin() { return m_values.begin(); }
};
int main() {
Foo f(1);
return 0;
}
MSVC and Clang (with libc++ enabled) compile fine for the same code. Isn't there a problem, when the iterator hops to the next values? How can it know, where in memory is the next value to iterate, if the allocator allocates different sizes than the standard allocator?
std::vector<int>is one type,std::vector<int, Mallocator<int> >is a different type. It is unspecified whetherstd::vector<int, Mallocator<int> >::iteratoris convertible tostd::vector<int>::iterator.A simple way they could be incompatible is they are defined within
vector, and so are themselves unrelated types.A simple way they could be compatible is that they are defined outside
vectorand aliased within it, and only depend on the element type parameter.The very simple fix is for
Footo use the correct type in it's declaration.