不能在初始值设定项列表中将非常量表达式从类型 'int' 缩小到'unsigned long long'
non-constant-expression cannot be narrowed from type 'int' to 'unsigned long long' in initializer list
int main(int argc, char const *argv[])
{
int x = 4;
int y = 2;
const int cell = x/y;
auto a = std::bitset<20>{cell}; //fails
auto b = std::bitset<20>(cell); //works
}
为什么std::bitset
不允许我在这里使用大括号构造,而是使用括号构造?如果cell
是constexpr
,则两者都将编译。
编译错误:
test.cpp:21:29: error: non-constant-expression cannot be narrowed from type 'int' to 'unsigned long long' in initializer list [-Wc++11-narrowing]
auto a = std::bitset<20>{x*y}; //fails
^~~
test.cpp:21:29: note: insert an explicit cast to silence this issue
auto a = std::bitset<20>{x*y}; //fails
^~~
static_cast<unsigned long long>( )
1 error generated.
失败的行使用列表初始化语法:
auto a = std::bitset<20>{cell}; //fails
该语法在C++17标准的11.6.4节中进行了定义。相关部分:
T
类型的对象或引用的列表初始化定义如下:(3.7(否则,如果
T
是类类型,则考虑构造函数。列举了适用的构造函数,并通过过载解析(16.3,16.3.1.7(选择了最佳构造函数。如果需要窄化转换(见下文(来转换任何参数,则程序格式错误窄幅转换是一种隐式转换
(7.4(从整数类型或无范围枚举类型到不能表示原始类型的所有值的整数类型,除非源是一个常量表达式,其值在整数提升后将适合目标类型。
这让我们更好地了解了正在发生的事情:
// Works, no narrowing check, implicit conversion.
std::bitset<20> a(2);
std::bitset<20> b(-1);
std::bitset<20> c(cell);
// Works, 2 can be converted without narrowing
std::bitset<20> d{2};
// Fails, -1 cannot be converted without narrowing
std::bitset<20> e{-1};
// Fails, compiler does not understand cell can be converted without narrowing
std::bitset<20> f{cell};
在您的程序中,编译器无法理解cell
是一个常量表达式。它检查std::bitset
的可用构造函数,并发现它必须从int
转换为unsigned long long
。它认为int
可能是负的,因此我们有一个缩小的转换。
我们可以通过使cell
成为比const
更强的constexpr
来解决这个问题。const
仅表示不应更改该值,constexpr
表示该值在编译时可用:
constexpr int x = 4;
constexpr int y = 2;
constexpr int cell = x / y;
auto a = std::bitset<20>{cell}; // works
您现在可以问为什么列表初始化不允许缩小转换范围。我不能完全回答这个问题。我的理解是,隐性狭窄通常被视为不可取的,因为它可能会产生意想不到的后果,因此被排除在外。
相关文章:
- (C++)分析树以计算返回错误值的简单算术表达式
- 在VS2010-VS2015下编译时,如何使用decltype作为较大类型表达式的LHS
- 如何在 C 中正确使用 libiconv 使其不会报告"Arg list too long"?
- 提升精神:解析布尔表达式并简化为规范范式
- 不能在初始值设定项列表中将非常量表达式从类型 'int' 缩小到'unsigned long long'
- 使用正则表达式regex_search在字符串中查找字符串
- 如何确认我的constexpr表达式实际上已经在编译时执行
- 在C++中使用GDAL可以将图像的像素坐标转换为lat,long吗
- 概念中的cv限定符需要表达式参数列表
- 为什么constexpr的性能比正常表达式差
- 对于结构,表达式必须是可修改的ivalue
- 当一个值是非常量但用常量表达式初始化时使用constexpr
- 将fold表达式与std::一起用于两个元组
- 断言中的Fold表达式在某些计算机上编译,但在其他计算机上不编译
- 标记 '","' 之前的预期主表达式
- gcc和clang在表达式是否为常量求值的问题上存在分歧
- 如何计算具有指定类型的表达式的相对精度和绝对精度
- 带有用户定义类的c++折叠表达式
- <Windows>为什么 std::thread::native_handle 返回类型为"long long unsigned int"的值,而不是 void*(又名 HANDLE)?
- 我有 3 个错误:期望一个")",期望一个表达式,long 类型的参数与 U32 类型的参数不兼容