Kra*_*lew 14 c c++ initialization narrowing c++11
非常简短
如何创建一个包含所有位的无符号常量?
...您可以使用{} s初始化字段,
......没有得到GCC 4.7.2的警告.
以下不满意:
struct U { unsigned ufield; };
struct Uc { unsigned char ufield; };
struct ULL { unsigned long long ufield; };
struct U32 { unsigned ufield; };
struct U64 { uint64_t ufield; }
typedef
//any of the above U Uc ULL U32 U64, we will arbitrarily choose:
U Ueg;
// somewhere far away
Ueg u = {-1}; // well defined by C standard, GCC 4.7.2 -Wnarrowing warning
Ueg u = {~0U}; // finit width constant, warnings in some places, silent non-all-1s-mask others
Ueg u = {~0ULL}; // ditto
Ueg u = {-1ULL}; // ditto
Run Code Online (Sandbox Code Playgroud)
基本上,用户,即编写{}初始化的人,不知道ufield的类型.他只知道它是一个无符号类型,但不知道它有多宽.它不完全是无符号类型.
*另一个原因我想要尽可能简单优雅的语法*
我不妨提一下其他内容:这里的"用户"实际上并不是在编写C或C++程序.他正在编辑配置文件.程序,简单的Perl或Python脚本,处理配置文件,并生成C代码.这个程序不是很复杂,目前通过看起来像的文本块
Foo: {-1,2,3};
Run Code Online (Sandbox Code Playgroud)
生成typedef结构Some_Struct {unsigned a; 无符号b,无符号c; Some_Struct = {-1,2,3}; //同上
基本上,我希望能够为一个文字提供一个友好的用户友好语法,该文字说明"此无符号值中的所有位都已设置".无需知道有多大的无符号.并且没有处理配置文件的程序变得太复杂.
以免潜在的答案提供者抱怨这是一个新的约束,不现实等等:
我对模板有完全相同的问题.即模板类型,我想写一个"无符号宽度,全1"的文字.在模板我可能更愿意做一些丑陋的,丑陋的,丑陋的语法,显然是能够做到这一点的,但我真的希望能有一个简单,优雅,语法.
*真正的问题*
问:有没有办法在不触发GCC 4.7.2警告的情况下创建一个"全1设置"的常量?
简要
我遇到了一个使用文字常量-1来初始化结构字段的程序,例如
> cat ./-1u.cpp
#include <stdio.h>
struct U { unsigned ufield; } ustruct = { -1 };
int main(int argc, char** argv)
{
printf("ustruct.ufield = %08x\n",ustruct.ufield);
}
Run Code Online (Sandbox Code Playgroud)
虽然早期版本的GCC在没有警告的情况下接受了这一点,但最新版本的GCC 4.7.2提供了一个警告:
> /SOME-PATH/import/gcc/gcc-4.7.2.pkg/installdir/bin/g++ -Wall ./-1u.cpp
./-1u.cpp:3:46: warning: narrowing conversion of '-1' from 'int' to 'unsigned int' inside { } is ill-formed in C++11 [-Wnarrowing]
Run Code Online (Sandbox Code Playgroud)
注意:这只是一个警告.将-1转换为无符号的结果在C/C++标准中得到了很好的定义:
> ./a.out
ustruct.ufield = ffffffff
Run Code Online (Sandbox Code Playgroud)
我不喜欢警告,所以我想沉默这个恼人的警告.我不想使用适用于整个文件的#pragmas,因为这可能会禁用对真正错误的警告.
(顺便说一句,只有在初始化字段时才能获得此警告.而不是在初始化非字段时
unsigned u = -1; // no cmpiler warning.
Run Code Online (Sandbox Code Playgroud)
干
struct U { unsigned ufield; } ustruct = { ~0U };
Run Code Online (Sandbox Code Playgroud)
沉默了.
但有人指出,如果字段的类型不是无符号的,而是uint64_t,则~0U提供的结果与-1:0x00000000FFFFFFFF不同,而不是0xFFFFFFFFFFFFFFFF.(即3位的32位,而不是1位的64位.)
struct U和initializaton代码可能存在于完全不同的地方,我们希望能够在不通知用户的情况下增加字段的大小,即位掩码.并且意图是获得所使用的无符号类型的"所有1的掩码".
同样
struct U { unsigned ufield; } ustruct = { -1u };
Run Code Online (Sandbox Code Playgroud)
沉默了.(令我惊讶的是 - 我不知道-1可以被认为是不受欢迎的.)
但也是有限宽度常数.
详情
这是一个测试程序..(顺便说一下,我的全部要求的是使用签字常量-1初始化一个无符号的部件等的警告只是测试你不要;吨需要向我解释,一个64位的数字不适合32位.)
sh-3.2$ cat ./-1u.cpp
#include <stdio.h>
unsigned um1 = -1;
unsigned un0u = ~0u;
unsigned un0ull = ~0ull;
struct Foo {
unsigned um1;
unsigned un0u;
unsigned un0ull;
};
Foo foo = { -1, ~0u, ~0ull };
int main(int argc, char** argv)
{
printf("um1 = %08x\n",um1);
printf("un0u = %08x\n",un0u);
printf("un0ull = %08x\n",un0ull);
printf("foo.um1 = %08x\n",foo.um1);
printf("foo.un0u = %08x\n",foo.un0u);
printf("foo.un0ull = %08x\n",foo.un0ull);
}
sh-3.2$ /mips/proj/performance/import/gcc/gcc-4.7.2.pkg/installdir/bin/gcc -Wall ./-1u.cpp
./-1u.cpp:7:20: warning: large integer implicitly truncated to unsigned type [-Woverflow]
./-1u.cpp:15:28: warning: narrowing conversion of '-1' from 'int' to 'unsigned int' inside { } is ill-formed in C++11 [-Wnarrowing]
./-1u.cpp:15:28: warning: narrowing conversion of '18446744073709551615ull' from 'long long unsigned int' to 'unsigned int' inside { } is ill-formed in C++11 [-Wnarrowing]
./-1u.cpp:15:28: warning: large integer implicitly truncated to unsigned type [-Woverflow]
sh-3.2$ /mips/proj/performance/import/gcc/gcc-4.7.2.pkg/installdir/bin/g++ -Wall ./-1u.cpp
./-1u.cpp:7:20: warning: large integer implicitly truncated to unsigned type [-Woverflow]
./-1u.cpp:15:35: warning: narrowing conversion of '-1' from 'int' to 'unsigned int' inside { } is ill-formed in C++11 [-Wnarrowing]
./-1u.cpp:15:35: warning: narrowing conversion of '18446744073709551615ull' from 'long long unsigned int' to 'unsigned int' inside { } is ill-formed in C++11 [-Wnarrowing]
./-1u.cpp:15:35: warning: large integer implicitly truncated to unsigned type [-Woverflow]
Run Code Online (Sandbox Code Playgroud)
在早期的编译器中不会发生:
sh-3.2$ /usr/bin/g++ -Wall ./-1u.cpp
./-1u.cpp:7: warning: large integer implicitly truncated to unsigned type
./-1u.cpp:15: warning: large integer implicitly truncated to unsigned type
/usr/bin/g++ --version
g++ (GCC) 4.1.2 20080704 (Red Hat 4.1.2-51)
Copyright (C) 2006 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Run Code Online (Sandbox Code Playgroud)
一个稍微用户友好的@Ali的回答版本:
#include <type_traits>
struct all_ones_type {
template <typename T,
typename = typename std::enable_if<std::is_unsigned<T>::value>::type>
constexpr operator T () const
{ return static_cast<T>(-1); }
} const all_ones;
#include <iostream>
struct X {
unsigned short a;
unsigned long b;
unsigned long long c;
};
int main() {
X x = { all_ones, all_ones, all_ones };
std::cout << x.a << "\n"
<< x.b << "\n"
<< x.c << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
根据您尝试转换为签名类型时想要发生的事情,您可以更改enable_if为允许所有整数类型,或者添加另一个带有nice的重载static_assert.
| 归档时间: |
|
| 查看次数: |
2708 次 |
| 最近记录: |