The code for boxing callables looks something like this:
rust::Box<::rust::Dyn<::rust::Fn<::int32_t, ::int32_t>>>
rust::Box<::rust::Dyn<::rust::Fn<::int32_t, ::int32_t>>>::make_box(
::std::function<::int32_t(::int32_t)> f) {
auto data = new ::std::function<::int32_t(::int32_t)>(f);
rust::Box<::rust::Dyn<::rust::Fn<::int32_t, ::int32_t>>> o;
::rust::__zngur_internal_assume_init(o);
__zngur_i32_i32_c11(
reinterpret_cast<uint8_t *>(data),
[](uint8_t *d) {
delete reinterpret_cast<::std::function<::int32_t(::int32_t)> *>(d);
},
[](uint8_t *d, uint8_t *i0, uint8_t *o) {
auto dd = reinterpret_cast<::std::function<::int32_t(::int32_t)> *>(d);
::int32_t oo =
(*dd)(::rust::__zngur_internal_move_from_rust<::int32_t>(i0));
::rust::__zngur_internal_move_to_rust<::int32_t>(o, oo);
},
::rust::__zngur_internal_data_ptr(o));
return o;
}
There are potentially three allocations here. The first is when the std::function argument is initialized, the second happens when data is allocated, and the third is when *data is initialized using its copy constructor.
An easy way to avoid one of these allocations is to use std::move when using new like this:
auto data = new ::std::function<::int32_t(::int32_t)>( std::move(f) );
However, I think it may be better to use a template interface:
template<typename... Args>
rust::Box<::rust::Dyn<::rust::Fn<::int32_t, ::int32_t>>>
rust::Box<::rust::Dyn<::rust::Fn<::int32_t, ::int32_t>>>::make_box( Args&&... args) {
auto data = new ::std::function<::int32_t(::int32_t)>(::std::forward<Args>(args)...);
// ...
return o;
}
This way you avoid the move and, once C++26 drops, you can switch to std::copyable_function which will allow your callers to use std::in_place_type_t as an argument and potentially gain further efficiency gains.
The code for boxing callables looks something like this:
There are potentially three allocations here. The first is when the
std::functionargument is initialized, the second happens whendatais allocated, and the third is when*datais initialized using its copy constructor.An easy way to avoid one of these allocations is to use
std::movewhen usingnewlike this:However, I think it may be better to use a template interface:
This way you avoid the move and, once C++26 drops, you can switch to
std::copyable_functionwhich will allow your callers to usestd::in_place_type_tas an argument and potentially gain further efficiency gains.