如何使用自定义分配器创建std :: function?

时间:2014-01-13 14:45:51

标签: c++ c++11 allocator

要保存一些代码,我可以说我有一个名为MyAlloc的自定义分配器,我已成功使用std::vector<int>,如下所示:

std::vector<int,MyAlloc<int>> vec;

现在我想使用自定义分配器在std :: function中保存lambda,我该怎么做?

我失败的尝试:

int i[100];
std::function<void(int)> f(MyAlloc<void/*what to put here?*/>{},[i](int in){
    //...
});

更新: std :: function中的分配器已depricated

2 个答案:

答案 0 :(得分:17)

根据标准,您需要提供tag type作为第一个参数,以表明您要使用自定义分配器:

std::function<void(int)> f(std::allocator_arg, MyAlloc<char>{}, [i](int in){
    //...
});

正如注释中@Casey@Potatoswatter所指出的那样,给分配器的模板参数类型无关紧要,只要它是一个对象类型即可。所以char在这里很好。

更新C ++ 17 :事实证明,std::function的分配器支持存在许多基本问题,导致它being deprecated in C++17。如果您坚持使用它,请务必在执行此操作之前仔细检查您的实施。 GCC的标准库从未实现过这些功能,但即使你的标准库有,它的行为也可能与你期望的不同。

答案 1 :(得分:1)

我意识到这个答案是正确的,但即使在阅读了这篇文章和回复之后,我仍然努力让语法正确,试图重载一个分配器for std :: function,它在VS2012中交叉编译X64,PS4和Xbox One

如果读者不清楚,您需要根据Casey的评论声明一个分配器类。虽然如果你阅读了所有的回复,这是相当明显的,但是这些分配器传递给对象的方式并不清楚,这与我之前使用过的大多数STL分配器不同。分配器类型(不是实例)作为类型规范的一部分。

对于std :: function,实例化的分配器被提供给std :: function对象的构造函数,这就是ComicSansMS在上面显示的内容。

对于使用成员函数而不是本示例中显示的lambda代码,这有点棘手:

   #include <functional>

    MyAllocType g_myAlloc; // declared somewhere and globally instantiated to persist

    // sample of a member function that takes an int parameter
    class MyClassType
    {
    public:
        void TestFunction( int param )
        {
        }
    };

    MyClassType MyClass; // instantiated object

    // example without allocator
    // note the pointer to the class type that must precede function parameters since 
    // we are using a method. Also std::mem_fn is require to compile in VS2012 :/
    std::function<void(MyClassType*, int)> f( std::mem_fn( &MyClassType::TestFunction ) );

    // usage of function needs an instantiated object (perhaps there is a way around this?)
    f( &MyClass, 10 );

    // example with allocator
    std::function<void(MyClassType*, int)> f(std::allocator_arg, g_myAlloc, std::mem_fn( &MyClassType::TestFunction ) );

    // usage of function is the same as above and needs an instantiated object 
    f( &MyClass, 10 );

    //or a non member function, which is much cleaner looking
    void NonMemberFunction( int param )
    {
    }

    std::function<void(int)> f(std::allocator_arg, g_myAlloc, NonMemberFunction);

希望这对人们有所帮助,我花了更长的时间才愿意承认这项工作,并且尽管我使用这个网站,但我认为如果没有其他人我会在这里发表评论比我自己如何使用它。 :)

对那些比我更聪明的人提出2个问题:

问:有没有办法将分配器包含在类型中?

问:有没有办法在没有对象实例的情况下使用成员函数?

要更新这个,如果您决定将其中一个std :: function对象作为参数传递给其他函数,我发现我需要使用std :: function :: assign,否则赋值会导致浅拷贝。如果您尝试将其传递给生命周期比原始生命周期更长的对象,则可能会出现问题。

示例:

std::function<void(MyClassType*, int)> f(std::allocator_arg, g_myAlloc, std::mem_fn( &MyClassType::TestFunction ) );

void FunctionTakeParam( std::function<void(MyClassType*, int)> &FunctionIn )
{
    // this results in a reallocation using your allocator
    std::function<void(MyClassType*, int)> MyLocalFunction.assign( std::allocator_arg, g_myAlloc, FunctionIn ); 

    // the below results in a shallow copy which will likely cause bad things
    //std::function<void(MyClassType*, int)> MyLocalFunction( std::allocator_arg, g_myAlloc, FunctionIn ); 

    ...
}