我遇到一个问题,模板函数使用
std::invoke
调用另一个函数,将 size_t
参数传递给需要 int32_t
的参数。从理论上讲,这应该会触发有关类型转换的警告。但是,当使用 -Wconversion
标志使用 GCC 或 Clang 进行编译时,不会发出警告,而 MSVC 会正确报告警告。
这是代码的简化版本:
void expectsInt32(int32_t) {
/* … */
}
template<typename Func, typename Arg>
void call(Func func, Arg arg) {
std::invoke(func, arg); // arg is size_t, potentially causing narrowing conversion
}
int main() {
size_t largeNumber = 4294967295; // Maximum value for uint32_t
call(expectsInt32, largeNumber); // Compiles without warning in GCC/Clang with -Wconversion
return 0;
}
在 MSVC 上,此代码会触发有关从 size_t 到 int32_t 转换期间潜在数据丢失的警告:
C:/data/msvc/14.39.33321-Pre/include\type_traits(1739): error C2220: the following warning is treated as an error
C:/data/msvc/14.39.33321-Pre/include\type_traits(1739): warning C4267: 'argument': conversion from 'size_t' to 'int32_t', possible loss of data
C:/data/msvc/14.39.33321-Pre/include\type_traits(1739): note: the template instantiation context (the oldest one first) is
<source>(18): note: see reference to function template instantiation 'void call<void(__cdecl *)(int32_t),size_t>(Func,Arg)' being compiled
with
[
Func=void (__cdecl *)(int32_t),
Arg=size_t
]
<source>(12): note: see reference to function template instantiation 'void std::invoke<void(__cdecl *&)(int32_t),Arg&,>(_Callable,_Ty1) noexcept(false)' being compiled
with
[
Arg=size_t,
_Callable=void (__cdecl *&)(int32_t),
_Ty1=size_t &
]
Compiler returned: 2
但是,即使启用了
-Wconversion
标志,GCC 或 Clang 也不会发出相同的警告。
为什么 GCC/Clang 不会在带有模板参数的
std::invoke
上下文中警告这种隐式转换?有没有办法强制执行此类警告或添加静态断言以在编译时捕获这些情况?
这是在编译器资源管理器上复制的代码:https://godbolt.org/z/KPPYM8cna
有没有办法强制执行此类警告
是的,使用 gcc,您可以使用标志
-Wsystem-headers
和 -Wconversion
来启用此类警告。 演示
警告在这里被抑制,因为它们发生在系统标头中。
有一个 gcc 错误: