如果缩小转换是可能的,则强制转换和失败编译
Cast and Fail Compilation if a narrowing conversion is possible
为了防止 "unexpected issues",使用格式指定在其他模块中定义类型的位置,我正在寻找一个将 编译失败 的转换运算符缩小转换:这表示需要解决的基本类型错误。
例如,最近从兼容类型更改为不兼容类型的一些外部 header 中的使用:
namespace y {
using X = uint64_t; // "recent change", was previously int32_t
}
目标是让它失败(错误不是 warning-as-error),因为结果用作 "%d
。
y::X a; // question covers ANY value in domain of X, not if overflow at run-time
int32_t r = cast_that_fails_to_compile_if_can_narrow<int32_t>(a);
// So this is guaranteed to always be a valid type specifier
// (per http://www.cplusplus.com/reference/cstdio/printf/)
// for the provided argument if the cast/code above compiles.
printf("%d", r);
(在这种情况下,棘手的缩小问题应该通过额外的代码更改来处理。)
用大括号(但不是圆括号)初始化不允许缩小转换:
int32_t r{a};
// or
int32_t r = {a};
// or
auto r = int32_t{a};
您的编译器可能无论如何都允许这样做,但这不符合标准 [1]。例如。对于 GCC,您需要添加 -pedantic-errors
标志才能实际生成硬错误。
另请注意 %d
的类型应为 int
。如果您改用 int32_t
,如果平台使用不同大小的 int
.
,您将面临类似问题的风险
你可以直接在printf
调用中使用它:
printf("%d", int{a});
[1] 该标准始终只要求编译器打印 some 诊断信息。它不需要阻止程序编译的硬错误。例如,GCC 仅在默认情况下发出警告,但这仍然符合要求。
可以创建一个模板函数来检查缩小转换但允许其他静态转换:
template <typename Tto, typename Tfr>
Tto static_cast_prohibit_narrow(Tfr v)
{
static_assert(sizeof(Tfr) <= sizeof(Tto), "Narrowing cast prohibited");
return static_cast<Tto>(v);
}
编译器在允许其他 static_casts 时遇到窄转换时产生错误。
int main()
{
long long int i1{ 4 };
int i2{ 5 };
//i2 = static_cast_prohibit_narrow<int>(i1); // Compiler static_assert error
i1 = static_cast_prohibit_narrow<int>(i2);
}
为了防止 "unexpected issues",使用格式指定在其他模块中定义类型的位置,我正在寻找一个将 编译失败 的转换运算符缩小转换:这表示需要解决的基本类型错误。
例如,最近从兼容类型更改为不兼容类型的一些外部 header 中的使用:
namespace y {
using X = uint64_t; // "recent change", was previously int32_t
}
目标是让它失败(错误不是 warning-as-error),因为结果用作 "%d
。
y::X a; // question covers ANY value in domain of X, not if overflow at run-time
int32_t r = cast_that_fails_to_compile_if_can_narrow<int32_t>(a);
// So this is guaranteed to always be a valid type specifier
// (per http://www.cplusplus.com/reference/cstdio/printf/)
// for the provided argument if the cast/code above compiles.
printf("%d", r);
(在这种情况下,棘手的缩小问题应该通过额外的代码更改来处理。)
用大括号(但不是圆括号)初始化不允许缩小转换:
int32_t r{a};
// or
int32_t r = {a};
// or
auto r = int32_t{a};
您的编译器可能无论如何都允许这样做,但这不符合标准 [1]。例如。对于 GCC,您需要添加 -pedantic-errors
标志才能实际生成硬错误。
另请注意 %d
的类型应为 int
。如果您改用 int32_t
,如果平台使用不同大小的 int
.
你可以直接在printf
调用中使用它:
printf("%d", int{a});
[1] 该标准始终只要求编译器打印 some 诊断信息。它不需要阻止程序编译的硬错误。例如,GCC 仅在默认情况下发出警告,但这仍然符合要求。
可以创建一个模板函数来检查缩小转换但允许其他静态转换:
template <typename Tto, typename Tfr>
Tto static_cast_prohibit_narrow(Tfr v)
{
static_assert(sizeof(Tfr) <= sizeof(Tto), "Narrowing cast prohibited");
return static_cast<Tto>(v);
}
编译器在允许其他 static_casts 时遇到窄转换时产生错误。
int main()
{
long long int i1{ 4 };
int i2{ 5 };
//i2 = static_cast_prohibit_narrow<int>(i1); // Compiler static_assert error
i1 = static_cast_prohibit_narrow<int>(i2);
}