C++ 如何使用自定义分配器创建std::函数?

C++ 如何使用自定义分配器创建std::函数?,c++,c++11,allocator,C++,C++11,Allocator,为了保存一些代码,假设我有一个名为MyAlloc的自定义分配器,我已成功地将其与std::vector一起使用,如下所示: std::vector<int,MyAlloc<int>> vec; std::向量向量向量机; 现在,我想使用自定义分配器在std::函数中保存lambda,我该怎么做 我失败的尝试: int i[100]; std::function<void(int)> f(MyAlloc<void/*what to put here?*

为了保存一些代码,假设我有一个名为
MyAlloc
的自定义分配器,我已成功地将其与
std::vector
一起使用,如下所示:

std::vector<int,MyAlloc<int>> vec;
std::向量向量向量机;
现在,我想使用自定义分配器在std::函数中保存lambda,我该怎么做

我失败的尝试:

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

更新:std::function中的分配器已根据标准进行了修改,您需要给出a作为第一个参数,以指示您要使用自定义分配器:

std::function<void(int)> f(std::allocator_arg, MyAlloc<char>{}, [i](int in){
    //...
});
函数f(std::allocator_arg,MyAlloc{},[i](int-in){ //... }); 正如和在注释中指出的,分配程序的模板参数类型并不重要,只要它是对象类型。所以
char
在这里很好


C++17的更新:事实证明,对
std::function
的分配器支持有许多基本问题,导致了它。如果您仍然坚持使用它,请确保在使用之前仔细检查您的实现。GCC的标准库从未实现过这些功能,但即使您的标准库实现了这些功能,它也可能不会按照您期望的方式运行。

我意识到这一点得到了正确的回答,但是,即使在阅读了本文和回复之后,我还是在尝试重载在VS2012的X64、PS4和Xbox One上交叉编译的std::function的分配器时,有点费劲地获得了正确的语法

如果读者不清楚,您需要根据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);
#包括
MyAllocType g_myAlloc;//在某处声明并全局实例化以持久化
//接受int参数的成员函数的示例
类MyClassType
{
公众:
void TestFunction(int参数)
{
}
};
MyClassType MyClass;//实例化对象
//不带分配器的示例
//请注意,指向类类型的指针必须位于函数参数之前,因为
//我们正在使用一种方法。还需要在VS2012中编译std::mem_fn:/
std::function f(std::mem_fn(&MyClassType::TestFunction));
//函数的使用需要一个实例化的对象(也许有办法解决这个问题?)
f(&MyClass,10);
//分配器示例
std::function f(std::allocator_arg、g_myAlloc、std::mem_fn(&MyClassType::TestFunction));
//函数的用法同上,需要实例化对象
f(&MyClass,10);
//或者是一个非成员函数,看起来更干净
void非成员函数(int参数)
{
}
std::函数f(std::分配器参数,g_myAlloc,非成员函数);
希望这对人们有所帮助,我花了比我想承认的时间更长的时间来完成这项工作,而且我使用这个网站时,我想我会在这里留下一条评论,如果除了我自己没有人知道如何使用它的话。:)

向比我聪明的人提出最后两个问题:

问:有没有办法将分配器作为类型的一部分包括在内

问:有没有一种方法可以在没有对象实例的情况下使用成员函数

为了更新这个,如果您决定将这些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 ); 

    ...
}
std::function f(std::allocator_arg、g_myAlloc、std::mem_fn(&MyClassType::TestFunction));
void FunctionTakeParam(std::function和FunctionIn)
{
//这将导致使用分配器进行重新分配
std::function MyLocalFunction.assign(std::allocator_arg、g_myAlloc、FunctionIn);
//下面的结果是一个浅拷贝,这可能会导致不好的事情
//std::function MyLocalFunction(std::allocator_arg、g_myAlloc、FunctionIn);
...
}

我看不到任何分配器支持。@RedX建议是这样的possible@RedX医生们都很好。请注意,PorkyBrain链接到
std::function
构造函数的文档,而您链接到类本身。分配器仅用于构造
std::function
,而不用于使用它。因此,只有构造函数是在分配器类型上模板化的,而不是类本身。@PorkyBrain您使用的是哪种编译器?我刚刚注意到VC在这里似乎有。有人建议从
std::function
中删除分配器支持:有一个有用的已知问题列表感谢您的帮助,它似乎在MSVC2013上工作,您确定MyAlloc的模板参数应该是空的吗?@PorkyBrain:Gut feeling=>任何类型都可以,因为
std::function
会将分配器重新绑定到另一个(内部)分配器类型。@PorkyBrain它几乎肯定与您为分配器使用的参数无关:
std::function
将立即将分配器重新绑定到它实际需要分配的任何内部类型,而您传递给构造函数的分配器将只用于复制该反弹分配器的构造。@PorkyBrain C++11§[func.wrap.func.con]/1声明“当调用任何具有类型
allocator\u arg\t
的第一个参数的函数构造函数时