我在编译以下代码时遇到 GCC 抱怨类型不匹配的问题:
#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 和 Clang(启用 libc++)可以很好地编译相同的代码。当迭代器跳转到下一个值时,没有问题吗?如果分配器分配的大小与标准分配器不同,它如何知道内存中下一个要迭代的值在哪里?
std::vector<int>
是一种类型,std::vector<int, Mallocator<int> >
是另一种类型。未指定 std::vector<int, Mallocator<int> >::iterator
是否可转换为 std::vector<int>::iterator
。
它们可能不兼容的一个简单方法是它们是在
vector
中定义的,因此它们本身是不相关的类型。
它们兼容的一个简单方法是它们在
vector
外部定义并在其中使用别名,并且仅依赖于元素类型参数。
非常简单的修复方法是
Foo
在其声明中使用正确的类型。
struct Foo
{
Foo(int f): m_values{f} {}
std::vector<int, Mallocator<int> > m_values;
std::vector<int, Mallocator<int> >::iterator begin() { return m_values.begin(); }
};