如何检测 std::vector::emplace_back 上的隐式转换损失整数精度

How to detect implicit conversion losses integer precision on std::vector::emplace_back

本文关键字:转换 精度 整数 损失 back emplace 何检测 检测 vector std      更新时间:2023-10-16

我使用编译器选项编译了以下代码-Wconversion以检测隐式转换丢失整数精度:

#include <vector>
#include <cstdint>
int main() {
std::vector<std::uint16_t> v;
std::uint32_t a = 0;
v.emplace_back(a);  // no warning
v.push_back(a);     // warning: implicit conversion loses integer precision
}

编译演示 https://wandbox.org/permlink/K5E4sUlfGBw6C5w8

向量的value_typestd::uint16_t。 如果我push_backstd::uint32_t向量的值,那么我如预期的那样收到以下警告。

prog.cc:8:17: warning: implicit conversion loses integer precision: 'std::uint32_t' (aka 'unsigned int') to 'std::__1::vector<unsigned short, std::__1::allocator<unsigned short> >::value_type' (aka 'unsigned short') [-Wimplicit-int-conversion]
v.push_back(a);     // warning: implicit conversion loses integer precision
~~~~~~~~~ ^
1 warning generated.

但是,如果我对向量emplace_back相同的值,则不会检测到警告。

我已经测试了它 clang++ 10.0.0、clang++ 9.0.0 和 g++ 9.3.0 并得到了相同的结果。

有没有好的方法可以检测 std::vector::emplace_back 上的隐式转换损失整数精度?

调用v.emplace_back(a)时没有隐式转换。如果您调用v.emplace_back<const std::uint16_t &>(a),则会有一个隐式转换。

push_backemplace_back之间的主要区别在于后者是模板,而前者不是。如果不为emplace_back指定模板参数,编译器将从函数参数推导它,这意味着在调用时不需要转换。在emplace_back内,转换发生在系统标头中,这会禁止显示警告。

所以在你的例子中,

v.emplace_back(a);

推导为

v.emplace_back<const std::uint32_t &>(a);

其中函数参数应为std::uint32_t.完美匹配,无需在系统标题之外进行转换。如果要在系统标头中启用警告,则最终可能会得到一堆虚假警告

要在代码中获得隐式转换,您需要强制emplace_back期望std::uint16_t,这可以通过

v.emplace_back<const std::uint16_t &>(a);

这将在调用emplace_back之前隐式地将a转换为std::uint16_t,以与push_back相同的方式触发编译器警告。