简体   繁体   English

转换一个class包装容器使用模板参数进行分配

[英]Convert a class wrapping a container to use template parameters for allocation

I have some classes which wrap STL containers我有一些包装 STL 个容器的类

For example:例如:

class Foo
{
private:
   class Bar
   {
    // stuff
   };

   using Container = std::vector<Bar>;

   Container contents;
};

I now find myself wanting to use custom allocators with Foo .我现在发现自己想对Foo使用自定义分配器。 How should I refactor the class without significantly increasing complexity or breaking encapsulation?我应该如何在不显着增加复杂性或破坏封装的情况下重构 class?

I must support platforms using compilers that do not yet support c++17 so I cannot use std::polymorphic_allocator (unless I use boost)我必须支持使用尚不支持c++17的编译器的平台,所以我不能使用std::polymorphic_allocator (除非我使用 boost)

This is essentially the same question as:这基本上与以下问题相同:

Should I pass allocator as a function parameter? 我应该将分配器作为 function 参数传递吗? (my misunderstanding about allocator) (我对分配器的误解)

But I found that question unclear.但我发现这个问题不清楚。 It gives the answer as use a template parameter but using this I struggled to make it work.它给出了使用template参数的答案,但使用它我很难让它工作。


What I would like to write is something like (pseudo-code not valid C++):我想写的是(伪代码无效的 C++):

template<typename X = std::allocator>
class Foo
{
    class Bar
    {
    };
    using Container = std::vector<Bar, X<Bar> >;

private:
    Container<Allocator> contents;
};

An allocator can be given as a template template parameter分配器可以作为template template parameter给出

The resulting template should look something like this:生成的模板应如下所示:

template<template <typename T> typename ALLOCATOR  = std::allocator>
class Foo
{
    class Bar
    {
    // stuff
    };

    using Allocator = ALLOCATOR<Bar>;
    using Container = std::vector<Bar, Allocator >;

    Foo(const Allocator& allocator = Allocator{}):
       contents(allocator)
    {
    }
private:
    Container<Allocator> contents;
};

You can now use it with std::allocator as:您现在可以将它与 std::allocator 一起使用,如下所示:

Foo<> asBefore;

or with your own allocator as:或使用您自己的分配器:

MyAllocator alloc(params); 
Foo<MyAllocator> foo(alloc);

You might be able to wrap your Container class using a trick like the one given here so that you don't have to convert the whole class to a template.您可以使用此处给出的技巧来包装容器 class,这样您就不必将整个 class 转换为模板。 This would let you keep your encapsulation.这会让你保持你的封装。 I have not attempted this here.我没有在这里尝试过。


Beware that:当心:

Foo<MyAllocator> foo(MyAllocator(params)); //BAD

Is a somewhat vexing parse which generally won't work.是一个有点令人烦恼的解析,通常不会起作用。

Also note that older compilers such as gcc 4.8 on RHEL7 do not allow typename for template template parameters so you must use class instead.另请注意,较旧的编译器(例如typename上的 gcc 4.8)不允许template template parameters使用类型名称,因此您必须改用class See How can I use templete template parameters in older C++ compilers?请参阅如何在较旧的 C++ 编译器中使用模板模板参数?

That is:那是:

template<template <class T> class ALLOCATOR  = std::allocator>
class Foo
...

For completeness, if you do have C++17 or later, another alternative is polymorphic allocators .为了完整起见,如果您有C++17或更高版本,另一种选择是 多态分配器 These potentially add the overhead of a virtual function call to every allocation but this is often less significant than the cost of a malloc .这些可能会增加每次分配的虚拟 function 调用的开销,但这通常不如malloc的成本重要。 In the right circumstances the compiler may be able to eliminate this completely.在适当的情况下,编译器可能能够完全消除这种情况。

See for example polymorphic_allocator: when and why should I use it?参见例如polymorphic_allocator:我应该何时以及为何使用它?

In this case your class wouldn't have to be converted into a template which may help with encapsulation.在这种情况下,您的 class 不必转换为可能有助于封装的模板。

class Foo
{
    class Bar
    {
    // stuff
    };

    using Container = std::pmr::vector<Bar>;

    Foo(const std::polymorphic_allocator& allocator = std::pmr::get_default_resource()):
       contents(allocator)
    {
    }
private:
    Container<Allocator> contents;
};

Note that std::pmr::vector<Bar> is basically shorthand for std::vector<Bar, std::pmr::polymorphic_allocator<Bar> > ;请注意, std::pmr::vector<Bar>基本上是std::vector<Bar, std::pmr::polymorphic_allocator<Bar> >的简写;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM