带有断言的C++ static_cast

Rai*_*Rai 4 c++

不幸的是,我必须在调用第三方库时执行缩小演员.我不想在我的发布版本中施加开销,因此将使用static_cast.然而,它是一个数组索引,如果它最终消极,可能导致一些娱乐.有没有办法在调试模式下创建一个安全的强制转换,它会检查值以确保在转换过程中没有丢失?我能想到的唯一方法是使用宏,而我宁愿不这样做.

例如,在使用MSVC的发布和调试模式下:

int main() {
  long long ll = std::numeric_limits<long>::max();
  ++ll;
  std::cout << ll << "\n";
  long l = static_cast<long>(ll);
  std::cout << l << "\n";
}
Run Code Online (Sandbox Code Playgroud)

结果输出:

2147483648
-2147483648
Run Code Online (Sandbox Code Playgroud)

使用宏:

template<class to, class from>
to checked_static_cast(const from& from_value) {
  to to_value = static_cast<to>(from_value);
  if (static_cast<from>(to_value) != from_value)
    throw std::runtime_error("Naughty cast");
  return to_value;
}

#ifdef _DEBUG
#define debug_checked_static_cast(to, val) checked_static_cast<to>(val)
#else
#define debug_checked_static_cast(to, val) static_cast<to>(val)
#endif

int main() {
  try {
    long long ll = std::numeric_limits<long>::max();
    ++ll;
    std::cout << ll << "\n";
    long l = debug_checked_static_cast(long, ll);
    std::cout << l << "\n";
  } catch (const std::exception& e) {
    std::cerr << "ERROR: " << e.what() << "\n";
  }
}
Run Code Online (Sandbox Code Playgroud)

在发布模式下产生相同的输出,但在调试中如下:

2147483648
ERROR: Naughty cast
Run Code Online (Sandbox Code Playgroud)

有更好的选择吗?

注意:我无视我们可能从一个足以引起这个问题的阵列中获得的娱乐,也许这只是过度偏执,但我想这个概念可能有我的特定要求以外的应用.

Ben*_*igt 7

不需要宏,只需在函数体内使用预处理器条件:

template<class to, class from>
inline to debug_checked_static_cast(const from& from_value) {
  to to_value{static_cast<to>(from_value)};
#if _DEBUG
  from round_trip{to_value};
  if (round_trip != from_value)
    throw std::runtime_error("Naughty cast");
#endif
  return to_value;
}
Run Code Online (Sandbox Code Playgroud)

template<class to, class from>
inline to debug_checked_coercion(const from& from_value) {
  to to_value{from_value};
#if _DEBUG
  from round_trip{to_value};
  if (round_trip != from_value)
    throw std::runtime_error("Naughty cast");
#endif
  return to_value;
}
Run Code Online (Sandbox Code Playgroud)

然后用

long l = debug_checked_coercion<long>(ll);
Run Code Online (Sandbox Code Playgroud)

请注意,我已经最小化了使用static_cast,因为缩小数字转换不需要它.