为什么GCC认为模板参数是int而它是一个完全不同的类型?

时间:2018-02-25 21:18:42

标签: c++ templates gcc

我在使用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==intMyAllocator我发现&#39; logDeallocation&#39;不是&#39; int&#39; 的成员。这是GCC中的错误吗?当我翻转模板参数(template<typename T, typename Tag)并将我的向量声明为std::vector<int, MyAllocator<int, Tag1>> vec;时,它会编译。

1 个答案:

答案 0 :(得分:21)

这不是一个符合标准的分配器,并将其作为一个提供给库组件会导致未定义的行为(因此,两个实现都是一致的)。您遗漏了!===,跨类隐式转化,以及rebind这里的相关内容。

allocator_traits的默认rebind实现假定值类型是第一个模板参数(并且任何剩余的模板参数都可以不经修改地重复使用)。由于您的分配器不是这种情况,您需要提供自己的rebind或反转模板参数顺序。

vector非常特别,因为如果需要,实现可以简单地使用提供的分配器而不重新绑定。这就是你的示例代码用libc ++编译的原因。 libstdc ++的容器支持允许你执行vector<int, allocator<char>>的扩展,因此它总是将分配器重新绑定到指定的value_type