【问题标题】:Compiler error on templated ctor (is this a compiler bug?)模板化 ctor 上的编译器错误(这是编译器错误吗?)
【发布时间】:2021-04-24 17:25:16
【问题描述】:

当我尝试在 Visual Studio 2019 中从 this post(见下文)编译代码时,我在模板复制 ctor 行收到以下编译器错误:

Error   C2439   'PreAllocator<_Newfirst>::memory_ptr': member could not be initialized
Error   C2440   'initializing': cannot convert from 'T *const ' to 'T *'
Error   C2248   'PreAllocator<int>::memory_size': cannot access private member declared in class 'PreAllocator<int>'    
Error   C2248   'PreAllocator<int>::memory_ptr': cannot access private member declared in class 'PreAllocator<int>' 

这是编译器错误还是我遗漏了什么?


template <typename T>
class PreAllocator
{
private:
    T* memory_ptr;
    std::size_t memory_size;

public:
    typedef std::size_t     size_type;
    typedef T* pointer;
    typedef T               value_type;

    PreAllocator(T* memory_ptr, std::size_t memory_size) : memory_ptr(memory_ptr), memory_size(memory_size) {}

    PreAllocator(const PreAllocator& other) throw() : memory_ptr(other.memory_ptr), memory_size(other.memory_size) {};

    template<typename U>
    PreAllocator(const PreAllocator<U>& other) throw() : memory_ptr(other.memory_ptr), memory_size(other.memory_size) {};

    template<typename U>
    PreAllocator& operator = (const PreAllocator<U>& other) { return *this; }
    PreAllocator<T>& operator = (const PreAllocator& other) { return *this; }
    ~PreAllocator() {}

    pointer allocate(size_type n, const void* hint = 0) { return memory_ptr; }
    void deallocate(T* ptr, size_type n) {}

    size_type max_size() const { return memory_size; }
};

int main()
{
    int my_arr[100] = { 0 };
    std::vector<int, PreAllocator<int>> my_vec(0, PreAllocator<int>(&my_arr[0], 100));
}

【问题讨论】:

标签: c++ visual-c++ compiler-errors visual-studio-2019


【解决方案1】:
template<typename U>
PreAllocator(const PreAllocator<U>& other) throw() : memory_ptr(other.memory_ptr), memory_size(other.memory_size) {};

此构造函数尝试从 U* 类型的 other.memory_ptr 初始化 T* 类型的 memory_ptr,这与 T* 不同(因为否则将调用复制构造函数)。 std::vector 实现显然使用内部类型来实例化分配器来分配存储,并且指向该类型的指针不能隐式转换为您所期望的 int*。

您必须显式转换指针,或者在内部存储void*,然后您将在allocate 成员函数中转换为T*。

template <typename T>
class PreAllocator
{
private:
    void* memory_ptr;

    ...

public:
    template<typename U>
    PreAllocator(const PreAllocator<U>& other) throw() :
        memory_ptr(other.memory_ptr), memory_size(other.memory_size) {}

    pointer allocate(size_type n, const void* hint = 0)
    {
        return static_cast< pointer >(memory_ptr);
    }

    ...
};

此外,在同一个构造函数中,您正在访问PreAllocator&lt;U&gt; 的memory_ptr 和memory_size 成员,这是与PreAllocator&lt;T&gt; 不同且不相关的类型(同样,因为T 和U 是不同种类)。这些成员在该类中是私有的,这会给您带来访问错误。

您可以通过将这些成员设为公共或为其添加公共访问器来缓解这种情况,或者通过如下声明使 PreAllocator 朋友的所有特化:

template <typename T>
class PreAllocator
{
    template< typename U >
    friend class PreAllocator;

    ...
};

【讨论】:

  • 感谢您的回答。这确实是解决方案。但是,也许我遗漏了一些东西,但我认为这个分配器类存在严重问题。我已经在另一篇文章中提出了要求:stackoverflow.com/q/65812813/547231。也许你可以看看。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-05
  • 2017-08-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-29
相关资源
最近更新 更多