前言
本文主要給大家介紹了關于C++17轉發一個函數調用的相關內容,分享出來供大家參考學習,下面話不多說了,來一起看看詳細的介紹吧。
方法如下
首先你靈光一閃:
#define WARP_CALL(fun, ...) fun(__VA_ARGS__)
不我們并不喜歡宏,擴展性太差了
template<class R, class T1, class T2, class T3>R warp_call(R(*fun)(T1, T2, T3), T1 a, T2 b, T3 c){ return fun(a, b, c);}
如果你寫出來上面這段代碼,你肯定是從C轉過來的,C++還沒用熟??紤]callable object和C++11 variadic template特性用上:
template<class Fun, class... Args>auto wrap_call(Fun f, Args... args) -> decltype(f(args...)){ return f(args...);}
加上移動語義,返回值推導:
template<class Fun, class... Args>auto wrap_call(Fun&& f, Args&&... args){ return std::forward<Fun>(f)(std::forward<Args>(args)...);}
auto返回值實際上會有參數被decay的問題,用decltype + 尾置返回值
template<class Fun, class... Args>auto wrap_call(Fun&& f, Args&&... args) -> decltype(std::forward<Fun>(f)(std::forward<Args>(args)...)){ return std::forward<Fun>(f)(std::forward<Args>(args)...);}
有了C++14,可以直接使用decltype(auto)
template<class Fun, class... Args>decltype(auto) wrap_call(Fun&& f, Args&&... args){ return std::forward<Fun>(f)(std::forward<Args>(args)...);}
別忘了noexcept
template<class Fun, class... Args>decltype(auto) wrap_call(Fun&& f, Args&&... args) noexcept(noexcept(std::forward<Fun>(f)(std::forward<Args>(args)...))){ return std::forward<Fun>(f)(std::forward<Args>(args)...);}
但是上面的函數不是SFINAE-friendly的,因為decltype(auto)返回值的函數并不能直接從函數簽名獲得返回值,而對這個函數進行返回值推導,是可能產生hard error打斷SFINAE的。所以最好手動寫返回值
template<class Fun, class... Args>auto wrap_call(Fun&& f, Args&&... args) noexcept(noexcept(std::forward<Fun>(f)(std::forward<Args>(args)...))) -> decltype(std::forward<Fun>(f)(std::forward<Args>(args)...)){ return std::forward<Fun>(f)(std::forward<Args>(args)...);}
我們還遺漏了啥?constexpr
template<class Fun, class... Args>constexpr auto wrap_call(Fun&& f, Args&&... args) noexcept(noexcept(std::forward<Fun>(f)(std::forward<Args>(args)...))) -> decltype(std::forward<Fun>(f)(std::forward<Args>(args)...)){ return std::forward<Fun>(f)(std::forward<Args>(args)...);}
上面是完美的
完美嗎?去看看std::invoke
總結
以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作能帶來一定的幫助,如果有疑問大家可以留言交流,謝謝大家對武林網的支持。
新聞熱點
疑難解答
圖片精選