c++ - 该标准是否会阻止在可变参数模板中使用足够小的文字值缩小文字转换的范围
问题描述
这是最小的示例:
#include <array>
template <class... T>
constexpr std::array<unsigned char, sizeof...(T)> act(T... aArgs)
{
return std::array<unsigned char, sizeof...(T)>{aArgs...};
}
int main()
{
act(5, 5);
}
编辑GCC 和 Clang 可以在没有投诉的情况下编译该片段不, 他们不能。
最新的 MSVC 失败并显示:
<source>(6): error C2397: conversion from 'int' to '_Ty' requires a narrowing conversion
with
[
_Ty=unsigned char
]
见:https ://godbolt.org/z/1PmeLk
- 由于在这种情况下,编译器拥有静态验证
act(5, 5)
对提供的值的调用不会溢出所需的一切,因此在此代码上失败是否符合标准的行为?
奖金问题:
- 由于没有文字后缀来获取 unsigned char 文字,如何解决这个错误
||
修复这个非标准代码?
解决方案
由于在这种情况下,编译器拥有静态验证
act(5, 5)
对提供的值的调用不会溢出所需的一切,因此在此代码上失败是否符合标准的行为?
是的。只有当编译器可以保证值可以用更窄的类型表示时,才允许编译器进行窄化转换。如果你有
std::array<unsigned char, 2> foo = {5, 127};
那么这没关系,因为编译器知道5
并且127
是可表示的。你的情况虽然不一样。您在函数内部进行初始化,并且函数内部{aArgs...}
没有相同的保证,因为它不是常量表达式(传递给函数的变量都不是常量表达式)。因此,编译器无法在所有情况下都证明它是有效的,因此它会发出警告/错误。
由于没有文字后缀来获取 unsigned char 文字,如何解决此错误 || 修复这个非标准代码?
您可以让自己的用户定义 litteral 来制作无符号字符,例如
inline constexpr unsigned char operator ""_uc( unsigned long long arg ) noexcept
{
return static_cast< unsigned char >( arg );
}
//...
act(5_uc, 5_uc);
或者你可以像投给他们一样
act((unsigned char)5, (unsigned char)5);
涵盖这种情况的实际措辞可以在[dcl.init]/7中找到
缩小转换是一种隐式转换 [...}
- 从整数类型或无作用域枚举类型到浮点类型,除非源是常量表达式并且转换后的实际值将适合目标类型,并且在转换回原始类型时将产生原始值 [. ..]
强调我的
如您所见,它要求初始化程序是一个常量表达式。由于函数参数从来都不是常量表达式,因此编译器进行多少静态分析以及它有多少证明都无关紧要。它不是一个常量表达式,因此无法完成。
推荐阅读
- sql-server - 基于文本框的 SQL Server 删除/插入不起作用。- 对比 2010
- javascript - 使用 axios 将 FormData 作为参数传递给发布请求
- javascript - 有没有办法以编程方式逐行抑制所有 ESLint 错误?
- php - Laravel 在 PHP 文件中使用模板横向
- c++ - 尝试从 Qt 中的指针检索按钮颜色
- javascript - 角度5业力单元测试:失败:无法读取未定义的属性子组件属性(itgroup)
- php - 将环境变量传递给 Apache PHP Docker 容器
- powershell - 我将如何将其格式化为表格?
- java - Java 语言中的 Android EMI 计算器:结果不正确,因为 Math.pow 给出的数字非常大
- siddhi - 在 siddhi 文件中更新或插入以忽略不可用的字段,而不是更新所有字段