使用 std::uint8_t 作为键初始化地图时的警告
Warnings when initialising map using std::uint8_t as key
问题
我正在尝试创建 std::uint8_t
-> char
的映射,并使用一些值对其进行初始化:
const std::map<std::uint8_t, char> ScenarioReader::alphabet = {
{ 0x12, 'b' },
{ 0x13, 'c' },
{ 0x15, 'a' },
{ 0x16, 'f' },
...
}
这会生成编译器警告,因为这些整数文字(0x12
等)被识别为 unsigned ints
,它们大于 std::uint8_t
:
1>d:\program files (x86)\microsoft visual studio17\community\vc\tools\msvc.16.27023\include\utility(172): warning C4244: 'initializing': conversion from '_Ty' to '_Ty1', possible loss of data
1> with
1> [
1> _Ty=unsigned int
1> ]
1> and
1> [
1> _Ty1=uint8_t
1> ]
1>d:\my-project\src\myfile.cpp(75): note: see reference to function template instantiation 'std::pair<const _Kty,_Ty>::pair<unsigned int,char,0>(_Other1 &&,_Other2 &&) noexcept' being compiled
1> with
1> [
1> _Kty=uint8_t,
1> _Ty=char,
1> _Other1=unsigned int,
1> _Other2=char
1> ]
1>d:\my-project\src\myfile.cpp(12): note: see reference to function template instantiation 'std::pair<const _Kty,_Ty>::pair<unsigned int,char,0>(_Other1 &&,_Other2 &&) noexcept' being compiled
1> with
1> [
1> _Kty=uint8_t,
1> _Ty=char,
1> _Other1=unsigned int,
1> _Other2=char
1> ]
解决方案
我知道有 2 种可能的方法可以解决此问题:
1) 禁用此部分的警告
#pragma warning( push )
#pragma warning( disable : 4244 )
const std::map<std::uint8_t, char> ScenarioReader::alphabet = {
{ 0x12, 'b' },
{ 0x13, 'c' },
{ 0x15, 'a' },
{ 0x16, 'f' },
...
}
#pragma warning( pop)
2) 显式转换每个键
const std::map<std::uint8_t, char> ScenarioReader::alphabet = {
{ static_cast<std::uint8_t>(0x12), 'b' },
{ static_cast<std::uint8_t>(0x13), 'c' },
{ static_cast<std::uint8_t>(0x15), 'a' },
{ static_cast<std::uint8_t>(0x16), 'f' },
...
}
我对这两种方法都不是特别满意,但第二种方法对我来说尤其难看。
我是否缺少更简单的解决方案?
文字的integer literal can never be an std::uint8_t
. Instead of using a static_cast
, you can make an explicit cast:
const std::map<std::uint8_t, char> alphabet = {
{ std::uint8_t(0x12), 'b' },
{ std::uint8_t(0x13), 'c' },
{ std::uint8_t(0x15), 'a' },
{ std::uint8_t(0x16), 'f' },
};
该警告是错误的,它仅在 \W4
警告级别上发生。
从字面量到 std::uint8_t
的转换不应生成任何警告,除非字面量超出转换类型的范围,而此处不是这种情况。
我认为您选择的任何选项都可以。归结为个人喜好问题。我个人更喜欢 std::uint8_t{0x12}
语法。
另一种选择是将警告级别降低到 \W3
,然后使用单独的 linter(\W4
大部分是 used for lint-like warnings)。
你可以写一个user-define文字
#include <cstdint>
constexpr std::uint8_t operator "" _ui8(unsigned long long value)
{
return static_cast<std::uint8_t>(value);
}
#include <type_traits>
int main() {
static_assert(std::is_same_v<decltype(0x12_ui8), std::uint8_t>);
}
问题
我正在尝试创建 std::uint8_t
-> char
的映射,并使用一些值对其进行初始化:
const std::map<std::uint8_t, char> ScenarioReader::alphabet = {
{ 0x12, 'b' },
{ 0x13, 'c' },
{ 0x15, 'a' },
{ 0x16, 'f' },
...
}
这会生成编译器警告,因为这些整数文字(0x12
等)被识别为 unsigned ints
,它们大于 std::uint8_t
:
1>d:\program files (x86)\microsoft visual studio17\community\vc\tools\msvc.16.27023\include\utility(172): warning C4244: 'initializing': conversion from '_Ty' to '_Ty1', possible loss of data
1> with
1> [
1> _Ty=unsigned int
1> ]
1> and
1> [
1> _Ty1=uint8_t
1> ]
1>d:\my-project\src\myfile.cpp(75): note: see reference to function template instantiation 'std::pair<const _Kty,_Ty>::pair<unsigned int,char,0>(_Other1 &&,_Other2 &&) noexcept' being compiled
1> with
1> [
1> _Kty=uint8_t,
1> _Ty=char,
1> _Other1=unsigned int,
1> _Other2=char
1> ]
1>d:\my-project\src\myfile.cpp(12): note: see reference to function template instantiation 'std::pair<const _Kty,_Ty>::pair<unsigned int,char,0>(_Other1 &&,_Other2 &&) noexcept' being compiled
1> with
1> [
1> _Kty=uint8_t,
1> _Ty=char,
1> _Other1=unsigned int,
1> _Other2=char
1> ]
解决方案
我知道有 2 种可能的方法可以解决此问题:
1) 禁用此部分的警告
#pragma warning( push )
#pragma warning( disable : 4244 )
const std::map<std::uint8_t, char> ScenarioReader::alphabet = {
{ 0x12, 'b' },
{ 0x13, 'c' },
{ 0x15, 'a' },
{ 0x16, 'f' },
...
}
#pragma warning( pop)
2) 显式转换每个键
const std::map<std::uint8_t, char> ScenarioReader::alphabet = {
{ static_cast<std::uint8_t>(0x12), 'b' },
{ static_cast<std::uint8_t>(0x13), 'c' },
{ static_cast<std::uint8_t>(0x15), 'a' },
{ static_cast<std::uint8_t>(0x16), 'f' },
...
}
我对这两种方法都不是特别满意,但第二种方法对我来说尤其难看。
我是否缺少更简单的解决方案?
文字的integer literal can never be an std::uint8_t
. Instead of using a static_cast
, you can make an explicit cast:
const std::map<std::uint8_t, char> alphabet = {
{ std::uint8_t(0x12), 'b' },
{ std::uint8_t(0x13), 'c' },
{ std::uint8_t(0x15), 'a' },
{ std::uint8_t(0x16), 'f' },
};
该警告是错误的,它仅在 \W4
警告级别上发生。
从字面量到 std::uint8_t
的转换不应生成任何警告,除非字面量超出转换类型的范围,而此处不是这种情况。
我认为您选择的任何选项都可以。归结为个人喜好问题。我个人更喜欢 std::uint8_t{0x12}
语法。
另一种选择是将警告级别降低到 \W3
,然后使用单独的 linter(\W4
大部分是 used for lint-like warnings)。
你可以写一个user-define文字
#include <cstdint>
constexpr std::uint8_t operator "" _ui8(unsigned long long value)
{
return static_cast<std::uint8_t>(value);
}
#include <type_traits>
int main() {
static_assert(std::is_same_v<decltype(0x12_ui8), std::uint8_t>);
}