Const限定符和前向引用

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Const限定符和前向引用相关的知识,希望对你有一定的参考价值。

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

所以,因为worklvalue make_task(Func&&)-> make_task(Func&)并且它将lambda_task实例化为lambda_task<Func&>导致这两个ctors

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_task对象实例化work会引发编译时错误

<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是冲突的,而且添加&&to 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)) {}

以上是关于Const限定符和前向引用的主要内容,如果未能解决你的问题,请参考以下文章

const限定符

为啥 const rvalue 限定 std::optional::value() 返回 const rvalue 引用?

机器学习-正则化(岭回归lasso)和前向逐步回归

成员函数上的 const 引用限定符 [重复]

2.6 const限定符与引用指针

using 声明能否仅引用基于 const 限定的特定重载?