有“安全的” static_cast替代方法吗?

时间:2018-10-17 14:54:28

标签: c++ c++11 type-safety narrowing safety-critical

在C ++ 11/14中,是否有static_cast的“安全”替代品或实现此功能的库?

“安全”是指演员表应只允许不损失精度的演员表。因此,只有在数字适合int64_t且报告了错误的情况下,才允许从int32_tint32_t的转换。

4 个答案:

答案 0 :(得分:35)

gsl::narrow

  

缩小// // @HostBindingnarrow<T>(x),如果static_cast<T>(x)或抛出static_cast<T>(x) == x

答案 1 :(得分:21)

您已经颠倒了用例。

static_cast(和其他c ++样式强制转换)的预期用途是指示程序员的意图。当您写auto value = static_cast<int32_t>(value_64);时,您是在说“是的,我非常想*贬低这个值,当我执行此分配时可能会截断它”。结果,通常情况下可能倾向于抱怨这种转换的编译器(例如,如果您编写了int32_t value = value_64;)则观察到”,程序员告诉我这是他们的意图是什么;他们为什么对我说谎?” 并会静默地编译代码。

如果您希望C ++代码对不安全的转换发出警告或引发错误,则需要明确地使用static_castconst_castreinterpret_cast,并让编译器完成工作。编译器具有更改警告处理方式的标志(将int64_t转换为int32_t通常只会产生警告),因此请确保使用正确的标志将警告视为错误。< / p>

答案 2 :(得分:0)

您可以使用sfinae创建自己的。这是一个示例:

template <typename T, typename U>
typename std::enable_if<sizeof(T) >= sizeof(U),T>::type 
safe_static_cast(U&& val)
{
    return static_cast<T>(val);
}

int main()
{
    int32_t y = 2;
    std::cout << safe_static_cast<int32_t>(y) << std::endl;
    std::cout << safe_static_cast<int16_t>(y) << std::endl; // compile error
}

仅当您投射到的尺寸> =源尺寸时,此选项才会编译。

尝试here

对于其他类型,您可以使用numeric_limitstype_traits将其进一步复杂化。

请注意,我的解决方案是编译时解决方案,因为您询问了static_cast,此处的静态是指“在编译时确定”。

答案 3 :(得分:0)

假设问题是关于潜在损失转化的编译时检测...

这里尚未提及的一个简单工具是列表初始化不允许缩小,因此您可以编写:

void g(int64_t n)
{
    int32_t x{n};   // error, narrowing

    int32_t g;
    g = {n};        // error, narrowing
}

NB。一些处于默认模式的编译器可能会显示“警告”,并继续对此格式错误的代码进行编译,通常您可以通过编译标志来配置此行为。