如果缩小转换是可能的,则强制转换和失败编译

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);
}