Сообщение Re[5]: Связать лямбду от 12.02.2018 20:49
Изменено 12.02.2018 21:02 Alexander G
Re[5]: Связать лямбду
Здравствуйте, Marty, Вы писали:
M>Кучи нет. Кстати
Ого. Ну как-то так можно, раз new запрещён, остаётся фиксированный буфер в себе:
M>Кучи нет. Кстати
Ого. Ну как-то так можно, раз new запрещён, остаётся фиксированный буфер в себе:
template<std::size_t BufferSize, class R, class... Args>
class LambdaStorage
{
public:
template<class F>
LambdaStorage(F f)
{
new (data) F(f);
call = CallImpl<F>;
copy = CopyImpl<F>;
del = DelImpl<F>;
}
LambdaStorage()
{
call = nullptr;
copy = nullptr;
del = nullptr;
}
LambdaStorage(const LambdaStorage& other)
{
call = other.call;
copy = other.copy;
del = other.del ;
copy(data, other.data);
}
~LambdaStorage()
{
if ( del != nullptr )
del(data);
}
LambdaStorage& operator=(const LambdaStorage& other) = delete;
R operator()(Args... args)
{
return call(data, args...);
}
private:
template<class F>
static R CallImpl(const char* data, Args... args)
{
const F* f = reinterpret_cast<const F*>(data);
return (*f)(args...);
}
template<class F>
static void CopyImpl(char* dest, const char* src)
{
const F* f = reinterpret_cast<const F*>(src);
new (dest) F(*f);
}
template<class F>
static void DelImpl(char* data)
{
const F* f = reinterpret_cast<const F*>(data);
f->~F();
}
R (*call) (const char* data, Args...);
void (*copy) (char* dest, const char* src);
void (*del) (char* data);
char data[BufferSize];
};
typedef LambdaStorage<16, int, const char*, int> MyCallable;
MyCallable MakeCallable()
{
int i = 22;
return [i](const char* s, int j)
{
std::cout << s << '\n';
return (i+j);
};
}
void UseCallable(MyCallable c)
{
int r = c("Hello world!", 20);
std::cout << "Result " << r << '\n';
}
int main()
{
MyCallable c = MakeCallable();
UseCallable(c);
return 0;
}
Re[5]: Связать лямбду
Здравствуйте, Marty, Вы писали:
M>Кучи нет. Кстати
Ого. Ну как-то так можно, раз new запрещён, остаётся фиксированный буфер в себе:
(решение подлежит оптимизации, если что, это наглядная версия)
M>Кучи нет. Кстати
Ого. Ну как-то так можно, раз new запрещён, остаётся фиксированный буфер в себе:
template<std::size_t BufferSize, class R, class... Args>
class LambdaStorage
{
public:
template<class F>
LambdaStorage(F f)
{
new (data) F(f);
call = CallImpl<F>;
copy = CopyImpl<F>;
del = DelImpl<F>;
}
LambdaStorage()
{
call = nullptr;
copy = nullptr;
del = nullptr;
}
LambdaStorage(const LambdaStorage& other)
{
call = other.call;
copy = other.copy;
del = other.del ;
copy(data, other.data);
}
~LambdaStorage()
{
if ( del != nullptr )
del(data);
}
LambdaStorage& operator=(const LambdaStorage& other) = delete;
R operator()(Args... args)
{
return call(data, args...);
}
private:
template<class F>
static R CallImpl(const char* data, Args... args)
{
const F* f = reinterpret_cast<const F*>(data);
return (*f)(args...);
}
template<class F>
static void CopyImpl(char* dest, const char* src)
{
const F* f = reinterpret_cast<const F*>(src);
new (dest) F(*f);
}
template<class F>
static void DelImpl(char* data)
{
const F* f = reinterpret_cast<const F*>(data);
f->~F();
}
R (*call) (const char* data, Args...);
void (*copy) (char* dest, const char* src);
void (*del) (char* data);
char data[BufferSize];
};
typedef LambdaStorage<16, int, const char*, int> MyCallable;
MyCallable MakeCallable()
{
int i = 22;
return [i](const char* s, int j)
{
std::cout << s << '\n';
return (i+j);
};
}
void UseCallable(MyCallable c)
{
int r = c("Hello world!", 20);
std::cout << "Result " << r << '\n';
}
int main()
{
MyCallable c = MakeCallable();
UseCallable(c);
return 0;
}
(решение подлежит оптимизации, если что, это наглядная версия)