Как я могу создать std:: функцию с помощью специального распределителя?
Чтобы сохранить некоторый код, скажем, у меня есть собственный распределитель с именем MyAlloc
, который я успешно использовал с std::vector<int>
следующим образом:
std::vector<int,MyAlloc<int>> vec;
теперь я хочу сохранить лямбда в std:: function, используя пользовательский распределитель, как это сделать?
Моя неудачная попытка:
int i[100];
std::function<void(int)> f(MyAlloc<void/*what to put here?*/>{},[i](int in){
//...
});
Обновление: распределители в std:: function были лишены
Ответы
Ответ 1
В соответствии со стандартом вам необходимо указать тип тега в качестве первого аргумента, чтобы указать, что вы хотите использовать собственный распределитель:
std::function<void(int)> f(std::allocator_arg, MyAlloc<char>{}, [i](int in){
//...
});
Как указано в @Casey и @Potatoswatter в комментариях, тип аргумента шаблона, присвоенный распределитель не имеет значения, если это тип объекта. Итак, char
здесь хорошо.
Обновление для С++ 17. Оказывается, что поддержка распределителя для std::function
имеет ряд фундаментальных проблем, которые приводят к этому устарел в С++ 17. Если вы, тем не менее, настаиваете на его использовании, прежде чем делать это, обязательно тщательно проверьте свою реализацию. Стандартная библиотека GCC никогда не выполняла эти функции, но даже если ваша стандартная библиотека делает это, она не будет вести себя так, как вы ожидаете.
Ответ 2
Я понимаю, что на это был дан ответ, но даже после прочтения этой статьи и ответов я немного пытался получить синтаксис, пытаясь перегрузить распределитель для std:: function, который перекрестно компилирует на X64, PS4 и Xbox One в VS2012.
Если это не понятно читателю, вам нужно будет объявить класс распределителя для комментария Casey. Хотя это довольно очевидно, если вы читаете все ответы, то, что было неясно, было то, как эти распределители передаются объекту, который не похож на большинство распределителей STL, которые я использовал до того, как взять тип распределителя (не экземпляр ) как часть спецификации типа.
Для std:: function для конструктора вашего объекта std:: function передается созданный экземпляр, который представляет собой ComicSansMS.
Для использования этого с функцией-членом вместо лямбда-кода, показанного в этом примере, это немного сложно:
#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 финальных вопроса тем, кто умнее меня:
Q: Есть ли способ включить распределитель как часть типа?
Q: Есть ли способ использовать функцию-член без экземпляра объекта?
Чтобы обновить это, если вы решите передать один из этих объектов 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 );
...
}