[英]Understanding the need for this `const&` specialization
在指南支持庫中有一個名為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 )
第一個需要什么? 如果我們只有第二個(使用轉發,也就是通用,引用)它不會做同樣的事情嗎?
讓我們考慮完美轉發版本:
當使用rvalue調用時,它將返回final_action<F>(static_cast<F&&>(f))
。
當使用左值調用時,它將返回final_action<F&>(f)
。
我們現在考慮const F&
overload:
final_action<F>(f)
。 如您所見,有一個重要的區別:
傳遞一個非const
左值參照finally
將產生存儲了一個包裝F&
將const
lvalue引用傳遞給finally
將生成一個存儲F
的包裝器
我不確定為什么認為有必要讓const F&
over。
這是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<F&>
並沒有多大意義,因為f_(std::move(f))
將無法編譯。
所以我認為這應該是:
template <class F>
inline final_action<F> finally(F&& f) noexcept
{
return final_action<std::decay_t<F>>(std::forward<F>(f));
}
最終,我認為finally
在GSL中的實現不正確/不理想(即冗余,有代碼重復)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.