代码之家  ›  专栏  ›  技术社区  ›  willj

编译时间方法,以确定对象是否具有自动存储持续时间

  •  3
  • willj  · 技术社区  · 11 年前

    我希望能够在编译时强制要求特定类型只能用于创建具有 自动的 储存持续时间。

    template<typename T, typename Alloc>
    struct Array
    {
        T* data; // owned resource
        Array(std::size_t size); // allocates via Alloc
        ~Array(); // deallocates via Alloc
    };
    
    typedef Array<int, AutoAllocator<int>> AutoArray;
    
    void foo(AutoArray a) // ok
    {
        AutoArray l = AutoArray(); // ok
        static AutoArray s; // error
        new AutoArray(); // error
        std::vector<AutoArray> v(1); // error
    }
    

    这样做的应用是为了能够为实例所拥有的资源选择最佳分配策略 AutoArray 。其思想是,具有 自动的 存储持续时间与后进先出法资源分配器兼容。

    我可以用什么方法在C++中实现这一点?

    编辑: 次要目标是允许 Array 通过插入任意一个进行透明切换 AutoAllocator 或默认 std::allocator .

    typedef Array<int, std::allocator<int>> DynamicArray;
    

    假设有大量的代码已经在使用 DynamicArray .

    1 回复  |  直到 11 年前
        1
  •  2
  •   David Rodríguez - dribeas    11 年前

    这是不可能做到的。假设您创建了一个将其作为成员的类型。当编译器为该类型的构造函数生成代码时,它不知道对象是在哪里创建的,完整的对象是在堆栈中还是在堆中?

    您需要以不同的心态来解决问题,例如,您可以将分配器传递给对象的构造函数( BSL 确实如此),并且可能默认为安全分配器(基于新的删除),那么对于那些lifo分配器是更好选择的用例,用户可以显式地请求它。

    这与编译器错误不同,但在代码审查时可以很明显地检测到。

    如果您真的对分配器的有趣用途感兴趣,您可能想看看标准库的BSL替代品,因为它允许将多态分配器传播到容器的成员。在BSL世界中,您的示例将变成:

    // Assume a blsma::Allocator implementing LIFO, Type uses that protocol
    LifoAllocator alloc;       // implements the bslma::Allocator protocol
    Type l(&alloc);            // by convention bslma::Allocator by pointer
    static Type s;             // defaults to new-delete if not passed
    new (&alloc) Type(&alloc); // both 'Type' and it's contents share the allocator
                               // if the lifetime makes sense, if not:
    new Type;                  // not all objects need to use the same allocator
    bsl::vector<Type> v(&alloc);
    v.resize(1);               // nested object uses the allocator in the container
    

    一般来说,使用分配器并不简单,您必须小心对象相对于彼此和分配器的相对生存期。