【问题标题】:Understanding the need for this `const&` specialization了解对这种 `const&` 专业化的需求
【发布时间】:2018-01-25 15:05:04
【问题描述】:

在 Guidelines Support Library 中有一个名为 final_action 的类(本质上是众所周知的 ScopeGuard)。有 2 个独立的便利函数可以生成这个模板类:

// finally() - convenience function to generate a final_action
template <class F>
inline final_action<F> finally(const F& f) noexcept
{
    return final_action<F>(f);
}

template <class F>
inline final_action<F> finally(F&& f) noexcept
{
    return final_action<F>(std::forward<F>(f));
}

(来源:https://github.com/Microsoft/GSL/blob/64a7dae4c6fb218a23b3d48db0eec56a3c4d5234/include/gsl/gsl_util#L71-L82

第一个需要什么?如果我们只有第二个(使用转发,也就是通用引用),它不会做同样的事情吗?

【问题讨论】:

    标签: c++ c++11 reference overloading guideline-support-library


    【解决方案1】:

    让我们考虑一下完美转发版本:

    • 当使用右值调用时,它将返回final_action&lt;F&gt;(static_cast&lt;F&amp;&amp;&gt;(f))

    • 当使用左值调用时,它将返回final_action&lt;F&amp;&gt;(f)

    现在让我们考虑const F&amp; 重载:

    • 当同时调用左值或右值时,它将返回final_action&lt;F&gt;(f)

    如您所见,有一个重要的区别:

    • 将非const 左值引用传递给finally 将生成一个存储F&amp; 的包装器

    • const 左值引用传递给finally 将生成一个存储F 的包装器

    live example on wandbox


    我不确定为什么认为有必要让const F&amp; 过载。

    这是final_action的实现:

    template <class F>
    class final_action
    {
    public:
        explicit final_action(F f) noexcept : f_(std::move(f)), invoke_(true) {}
    
        final_action(final_action&& other) noexcept 
            : f_(std::move(other.f_)), invoke_(other.invoke_)
        {
            other.invoke_ = false;
        }
    
        final_action(const final_action&) = delete;
        final_action& operator=(const final_action&) = delete;
    
        ~final_action() noexcept
        {
            if (invoke_) f_();
        }
    
    private:
        F f_;
        bool invoke_;
    };
    

    除非我遗漏了什么,否则实例化 final_action&lt;F&amp;&gt; 并没有什么意义,因为 f_(std::move(f)) 不会编译。

    live example on wandbox

    所以我认为这应该是:

    template <class F>
    inline final_action<F> finally(F&& f) noexcept
    {
        return final_action<std::decay_t<F>>(std::forward<F>(f));
    }
    

    最终,我认为 GSL 中 finally 的实现不正确/不理想(即冗余,有代码重复)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-07
      • 2017-06-24
      • 1970-01-01
      • 1970-01-01
      • 2011-05-15
      • 2021-01-28
      • 1970-01-01
      • 2014-06-27
      相关资源
      最近更新 更多