C++ SonarLint告警:std::forward仅应作用于转发引用修复方案
告警有效性判定
该告警不是SonarLint误报,是完全符合C++语义规范的有效告警。
- 转发引用(原称万能引用)的成立有严格的语法要求:只有当函数参数写法为
T&&,且T是当前函数模板在调用点现场推导的模板参数时,该参数才属于转发引用,只有这种场景下使用std::forward保留参数原始值类别的用法才是正确的。 - 你当前代码里,
duration函数的第一个参数F&& f满足转发引用要求,对其调用std::forward<F>(f)是合法正确的。 - 第二个参数包的声明是
Args... args,属于值传递的普通函数形参,完全不满足转发引用的语法要求,此时对其调用std::forward<Args>(args)...属于错误用法,触发告警是合理的。
规范修复方案
根据你的代码逻辑(计时包装可调用对象),最合理的修复方式是将参数包改为转发引用形式,既符合C++开发规范、消除告警,还能实现参数的完美转发,避免不必要的拷贝/移动开销,不影响计时准确性。
修复后的完整可运行代码如下:
#include <iostream> #include <chrono> #include <utility> #include <functional> template < typename Time = std::chrono::microseconds, typename Clock = std::chrono::steady_clock > struct FunctionTimer { template < typename F, typename... Args > static Time duration( F&& f, Args&&... args ) // 给参数包加上&&,构成转发引用 { auto start { Clock::now( ) }; // 此处std::forward的用法完全合规,无需改动 std::invoke( std::forward<F>( f ), std::forward<Args>( args )... ); auto end { Clock::now( ) }; return std::chrono::duration_cast<Time>( end - start ); } }; void test_func( const int param ) { std::cout << param << " Testing...\n"; } int main( ) { const auto time { FunctionTimer<>::duration( test_func, 5 ) }; std::cout << std::chrono::duration<double, std::milli>( time ).count( ) << '\n'; }
特殊场景说明:如果你明确要求参数必须按值传递,不需要做完美转发,那直接去掉参数包外层的
std::forward,直接传入args...即可消除告警,只是会额外产生一次参数的拷贝/移动开销,计时场景下不推荐这种写法。
内容的提问来源于stack exchange,提问作者digito_evo
相关产品推荐
相关产品推荐

