当前位置: 首页 > 知识库问答 >
问题:

C自定义分配器大小参数作为模板参数会引发编译器错误

赏光霁
2023-03-14

当我为我的容器使用自定义分配器时,以下代码给了我预期的结果(将大小sz保留为全局变量)

#include <cstddef> /* size_t */
#include <new> /* Only for bad_alloc */
#include <vector>
using std::vector;
#include <iostream>
using std::cout;
using std::endl;
std::size_t constexpr sz = 4;
template <typename T> class StaticAllocator {
protected:
    static T buf[sz];
public:
    typedef T value_type;
    T* allocate(std::size_t const n) {
        if (n > sz) throw std::bad_alloc();
        return buf;
    }
    void deallocate(T*, std::size_t) {}
};
template<typename T> T StaticAllocator<T>::buf[sz];
int main(void) {
    std::vector<char, StaticAllocator<char> > v;
    v.push_back('a');
    v.push_back('b');
    for (auto const& i : v) cout << i << endl;
}

其中,当我尝试将大小用作类的模板参数时,此版本的代码会给我带来编译器错误

#include <cstddef> /* size_t */
#include <new> /* bad_alloc */
#include <vector>
using std::vector;
#include <iostream>
using std::cout;
using std::endl;
template<typename T, std::size_t sz> class StaticAllocator {
protected:
    static T buf[sz];
public:
    typedef T value_type;
    T* allocate(std::size_t const n) {
        if (n > sz) throw std::bad_alloc();
        return buf;
    }
    void deallocate(T*, std::size_t) {}
};
template<typename T, std::size_t sz> T StaticAllocator<T, sz>::buf[sz];
int main(void) {
    std::vector<char, StaticAllocator<char, 4> > v;
    v.push_back('a');
    v.push_back('b');
    for (auto const& i : v) cout << i << endl;
}

共有1个答案

权承
2023-03-14

要从类型T的分配器中获取某些类型U的分配器,成员别名模板std::allocator\U traits::rebind\U alloc

Alloc::重新绑定

请注意,参数是类型模板参数。在您的分配器中没有重新绑定。在第一种情况下

您需要手动添加重新绑定成员结构:

template<typename T, std::size_t sz>
class StaticAllocator {
    // ...

    template<class U>
    struct rebind {
        using other = StaticAllocator<U, sz>;
    };
};

还要注意,对于某些常规类型,您的分配器已损坏。首先,默认情况下,将初始化buf,构建sz对象S。然后,在破坏现有的之前,在同一位置新构造的SS将覆盖它。在重新分配时也会发生类似的事情。这可能导致未定义的行为。有关详细信息,请参阅此和此问题。

在现在删除的答案中提出了以下解决方案:从std::分配器继承

template<typename T, std::size_t sz> class StaticAllocator : 
    public std::allocator<T> {
// ...
};

代码编译并运行,但是StaticAllocator::allocate和StaticAllocator::deallocate不被调用(至少在libstdc中是这样)。原因是在内部,std::vector始终使用重新绑定来获取分配器类型:

using Tp_alloc_type = 
    typename gnu_cxx::alloc_traits<Alloc>::template rebind<Tp>::other;

重新绑定继承自std::分配器

 类似资料:
  • 本章将介绍Rust编译器的参数。 Rust编译器程序的名字是rustc,使用它的方法很简单: $ rustc [OPTIONS] INPUT 其中,[OPTIONS]表示编译参数,而INPUT则表示输入文件。而编译参数有以下可选: -h, --help - 输出帮助信息到标准输出; --cfg SPEC - 传入自定义的条件编译参数,使用方法如 fn main() { if cfg!(he

  • 当我编译时,我得到了这些错误:

  • 我目前有一个,但是为了灵活性,我希望能够分配一个lambda表达式,将作为映射中的值返回。 所以我创建了这个模板类: 并像这样使用它: IntelliSense提供了更多信息: 多个操作符“=”匹配这些操作数:function“valueorfunction::operator=(const std::function&other)[with T=std::wstring]”function“va

  • 本章将介绍Rust语言中的属性(Attribute)和编译器参数(Compiler Options)。

  • 我正在努力研究如何在swagger editor中定义字典类型。我的POST方法的一个参数叫做“角色”,它的值是一个字典,其中键是电子邮件地址,值是整数。

  • C++ 引用 我们已经讨论了如何使用指针来实现引用调用函数。下面的实例使用了引用来实现引用调用函数。#include <iostream> using namespace std; // 函数声明 void swap(int& x, int& y); int main () { // 局部变量声明 int a = 100; int b = 200; cout << "交换前,a 的值:" << a