常量限定符和前向引用

Const qualifier and forward reference

本文关键字:引用 常量      更新时间:2023-10-16

在seastar框架中看到过这段代码

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{};}//为简单起见

让我们假设我将像下面这样实例化task

auto work = [](){...}
make_task(work);

因此,由于work是一个lvaluemake_task(Func&&)->make_task(Func&)并且它将lambda_task实例化为导致这两个 ctor 的lambda_task<Func&>

lambda_task(scheduling_group sg, const Func& func)
lambda_task(scheduling_group sg, Func&& func)

成为(我认为会)

lambda_task(scheduling_group sg, **const Func& func**)
lambda_task(scheduling_group sg, **Func& func**)

使用对象实例化lambda_taskwork引发编译时错误

<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]'

我为让它工作所做的是我改变了

lambda_task(scheduling_group sg, Func&& func) to
lambda_task(scheduling_group sg, std::remove_reference_t<Func>&& func)

问题1:我是对还是错?我的更改会破坏任何东西吗?还是需要?

我意识到

lambda_task(scheduling_group sg, const Func& func)#1
lambda_task(scheduling_group sg, Func && func)#2

#1 & #2是冲突的,此外,向Func添加&&并不能使其成为rvalue,因为它的引用折叠为lvalue(所以我使用了std::remove_reference_t )

问题2: 假设T&&是一个前向引用 [T=int] 并折叠成T&。 为什么std::is_same<const int&, const T&>不是真的?

<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,"");

为什么向折叠的引用添加const不起作用?

还是我的观察是错误的?

表示template <typename T> class lambda_task, 带有lambda_task<F&>, 我们有

  • const T&=T const&=F&
  • T&&=F&.

您可能希望将两个T衰减为分别具有const F&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)) {}