我在使用GCC编译以下程序时遇到问题(我尝试了很多版本,所有版本都失败并出现同样的错误)。它在Clang编写得很好:
#include <vector>
struct Tag1
{
static void logAllocation(){}
static void logDeallocation(){}
};
struct Tag2
{
static void logAllocation(){}
static void logDeallocation(){}
};
template<typename Tag, typename T>
struct MyAllocator
{
using value_type = typename std::allocator<T>::value_type;
T* allocate(std::size_t n)
{
Tag::logAllocation();
return std::allocator<T>{}.allocate(n);
}
void deallocate(T* p, std::size_t n)
{
Tag::logDeallocation();
std::allocator<T>{}.deallocate(p, n);
}
};
int main()
{
std::vector<int, MyAllocator<Tag1, int>> vec;
}
问题是GCC认为Tag==int
内MyAllocator
我发现&#39; logDeallocation&#39;不是&#39; int&#39; 的成员。这是GCC中的错误吗?当我翻转模板参数(template<typename T, typename Tag
)并将我的向量声明为std::vector<int, MyAllocator<int, Tag1>> vec;
时,它会编译。
答案 0 :(得分:21)
这不是一个符合标准的分配器,并将其作为一个提供给库组件会导致未定义的行为(因此,两个实现都是一致的)。您遗漏了!=
,==
,跨类隐式转化,以及rebind
这里的相关内容。
allocator_traits
的默认rebind
实现假定值类型是第一个模板参数(并且任何剩余的模板参数都可以不经修改地重复使用)。由于您的分配器不是这种情况,您需要提供自己的rebind
或反转模板参数顺序。
vector
非常特别,因为如果需要,实现可以简单地使用提供的分配器而不重新绑定。这就是你的示例代码用libc ++编译的原因。 libstdc ++的容器支持允许你执行vector<int, allocator<char>>
的扩展,因此它总是将分配器重新绑定到指定的value_type
。