禁止具有精度损失的整数转换 [英] Forbid integer conversion with precision loss

查看:74
本文介绍了禁止具有精度损失的整数转换的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何防止此类代码编译?

How to prevent such code from compiling?

#include <vector>
#include <limits>
#include <iostream>
#include <cstdint>

int main() {
  std::vector<int16_t> v;
  v.emplace_back(std::numeric_limits<uint64_t>::max());
  std::cout << v.back() << std::endl;
  return 0;
}

g ++和带有 -std = c ++ 14的clang -Wall -Wextra -Werror -pedantic -Wold-style-cast -Wconversion -Wsign-conversion 甚至都没有发出警告.该示例还使用 std :: vector< uint16_t>

g++ and clang with -std=c++14 -Wall -Wextra -Werror -pedantic -Wold-style-cast -Wconversion -Wsign-conversion don't even warn about it. The example also compiles without warnings with std::vector<uint16_t>

推荐答案

在命令行中添加 -Wsystem-headers .在许多虚假警告中,您会找到所需的警告.

Add -Wsystem-headers to the command line. Among the many spurious warnings you will find the desired warning.

In file included from (...)include/c++/6.3.0/x86_64-w64-mingw32/bits/c++allocator.h:33:0,
                 from (...)include/c++/6.3.0/bits/allocator.h:46,
                 from (...)include/c++/6.3.0/vector:61,
                 from test.cpp:1:
(...)include/c++/6.3.0/ext/new_allocator.h: In instantiation of 'void __gnu_cxx::new_allocator<_Tp>::construct(_Up*, _Args&& ...) [with _Up = short int; _Args = {long long unsigned int}; _Tp = short int]':
(...)include/c++/6.3.0/bits/alloc_traits.h:455:4:   required from 'static void std::allocator_traits<std::allocator<_Tp1> >::construct(std::allocator_traits<std::allocator<_Tp1> >::allocator_type&, _Up*, _Args&& ...) [with _Up = short int; _Args = {long long unsigned int}; _Tp = short int; std::allocator_traits<std::allocator<_Tp1> >::allocator_type = std::allocator<short int>]'
(...)include/c++/6.3.0/bits/vector.tcc:96:30:   required from 'void std::vector<_Tp, _Alloc>::emplace_back(_Args&& ...) [with _Args = {long long unsigned int}; _Tp = short int; _Alloc = std::allocator<short int>]'
test.cpp:9:54:   required from here
(...)include/c++/6.3.0/ext/new_allocator.h:120:4: error: conversion to 'short int' from 'long long unsigned int' may alter its value [-Werror=conversion]
  { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
    ^

我知道这不是一个真正的解决方案,尽管它从技术上回答了这个问题.

I know this is not a real solution, although it technically answers the question.

问题在于, emplace_back 将所有参数(在本例中为 uint64_t )转发到所包含类型的构造函数.首先,将 emplace_back 的参数推导为 uint64_t .调用emplace返回时不会发生任何转换.然后,缩小转换发生在系统头文件中的 emplace_back 实现内部.编译器不知道这是调用者的错,并且抑制了警告,因为它在系统头文件中.

The problem is, that emplace_back forwards all the arguments, in this case the uint64_t to the constructor of the contained type. First the argument to emplace_back is deduced as uint64_t. No conversion happens at the call of emplace back. The narrowing conversion then happens "inside" the emplace_back implementation in the system header. The compiler does not know that this is the fault of the caller and suppresses the warning because it is in a system header.

这篇关于禁止具有精度损失的整数转换的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆