我在使用 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
我得到一个错误,'logDeallocation' 不是'int'的成员。这是 GCC 中的错误吗?当我翻转模板参数( template<typename T, typename Tag
)并将我的 vector 声明为 std::vector<int, MyAllocator<int, Tag1>> vec;
它编译。</p>
最佳答案
这不是一个符合要求的分配器,将它作为一个分配器提供给库组件会导致未定义的行为(因此,两个实现都是符合要求的)。你不见了!=
, ==
,跨类型隐式转换,以及与此处相关的 rebind
.
allocator_traits
的默认值 rebind
实现假定值类型是第一个模板参数(并且任何剩余的模板参数都可以不加修改地重用)。由于您的分配器并非如此,因此您需要提供自己的 rebind
或反转模板参数顺序。
vector
非常特别的是,如果需要,实现可以简单地按原样使用提供的分配器而无需重新绑定(bind)。这就是您的示例代码使用 libc++ 编译的原因。 libstdc++ 的容器支持允许您执行 vector<int, allocator<char>>
的扩展,所以它总是将分配器重新绑定(bind)到指定的 value_type
.
关于c++ - 为什么 GCC 认为模板参数是 int 而它是完全不同的类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48978576/