Have seen this code in the seastar framework
template <typename Func>
class lambda_task final : public task {
Func _func;
public:
lambda_task(scheduling_group sg, const Func& func) : task(sg),
_func(func) {}
lambda_task(scheduling_group sg, Func&& func) : task(sg),
_func(std::move(func)) {}
virtual void run_and_dispose() noexcept override {
_func();
delete this;
}
};
template <typename Func>
inline std::unique_ptr<task> make_task(Func&& func) {
return std::make_unique<lambda_task<Func>>(current_scheduling_group(),
std::forward<Func>(func));
}
using scheduling_group = int;
auto current_scheduling_group(){ return int{};}
//for simplicity
let us assume I am going to instantiate task
like below
auto work = [](){...}
make_task(work);
so since the work
is an lvalue
make_task(Func&&)
->make_task(Func&)
and it instantiate lambda_task
as lambda_task<Func&>
which causes these two ctors
lambda_task(scheduling_group sg, const Func& func)
lambda_task(scheduling_group sg, Func&& func)
to become(I assume it would)
lambda_task(scheduling_group sg, **const Func& func**)
lambda_task(scheduling_group sg, **Func& func**)
the instantiation of lambda_task
with work
object is throwing a compile-time error
<source>:127:5: error: 'lambda_task<Func>::lambda_task(scheduling_group, Func&&) [with Func = main()::<lambda()>&; scheduling_group = int]'
cannot be overloaded with 'lambda_task<Func>::lambda_task(scheduling_group, const Func&) [with Func = main()::<lambda()>&; scheduling_group = int]'
lambda_task(scheduling_group sg, Func&& func) : task(sg), _func(std::move(func)) {}
^~~~~~~~~~~
<source>:126:5: note: previous declaration 'lambda_task<Func>::lambda_task(scheduling_group, const Func&)
[with Func = main()::<lambda()>&; scheduling_group = int]'
and what I did to make it work is I've changed
lambda_task(scheduling_group sg, Func&& func) to
lambda_task(scheduling_group sg, std::remove_reference_t<Func>&& func)
question 1: was I right or wrong? will my change break anything? or it is needed?
I realized that the
lambda_task(scheduling_group sg, const Func& func)#1
lambda_task(scheduling_group sg, Func && func)#2
#1 & #2
is conflicting and moreover adding &&
to Func
doesn't make it as an rvalue
as it was reference collapsed to lvalue
(so I used std::remove_reference_t )
question 2:
assume T&&
is a forward reference [T=int] and collapsed into T&
.
why std::is_same<const int&, const T&>
isn't true?
<source>:162:5: required from 'void maketest(T&&) [with T = int&]'
<source>:154:18: error: static assertion failed
static_assert(std::is_same<const int&,const T&>::value,"");
why adding const
to a collapsed reference isn't taking any effect?
or my observation is wrong?
for template <typename T> class lambda_task
, with lambda_task<F&>
,
we have
const T&
= T const&
= F&
T&&
= F&
.You probably want to decay both T
to have respectively const F&
and F&&
:
lambda_task(scheduling_group sg, const std::decay_t<Func>& func) : task(sg), _func(func) {}
lambda_task(scheduling_group sg, std::decay_t<Func>&& func) : task(sg), _func(std::move(func)) {}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With