初始化一个常量变量,如果失败则断言(c++)

Initialize a constant variable and assert if failed (c++)

本文关键字:失败 如果 断言 c++ 常量 一个 初始化 变量      更新时间:2023-10-16

我想用map中的值初始化const变量,并且想断言map中是否不包含这样的值

有什么优雅的方法来实现这一点吗?

我希望c++ ternary operator ?:能帮助我解决这个问题,但这段代码不起作用,因为ternary operator希望在两边具有相同的类型。

const auto it = modeMap.find(key);
const Mode myMode = (it != modeMap.end()) ? myMode = it->second : assert(false && "Mode doesn't exist"); 

错误C2440: '初始化':不能从'void'转换为'const '模式"

如果您愿意用assert来引发异常(无论如何可能是一个好主意),您可以通过调用std::map::at来简化代码:

const Mode myMode = modeMap.at(key);

如果key不在映射中,将触发std::out_of_range。如果您确实需要assert,那么您可以将逻辑包装在函数中:

const Mode& find_or_assert(const std::map<Key, Mode>& modeMap, const Key& key)
{
  auto it = modeMap.find(key);
  assert(it != modeMap.end());
  return it->second;
}
然后

const Mode myMode = find_or_assert(modeMap, key);

如果到达assert部分,则myMode无法初始化,因为assert没有返回任何内容(void)。您可以通过使用逗号操作符来解决这个问题:

const Mode myMode =
(it != modeMap.end()) ? myMode = it->second : (assert(false && "Mode doesn't exist"), SOME_VALUE);

assert执行时用SOME_VALUE初始化myMode


无论如何,您使用assert似乎无效。查看如何正确使用

最优雅的解决方案是@juanchopanza,但是如果您想要assert而不抛出异常:

依我之见,最好为这项工作定义如下的职能:

const auto it = modeMap.find(key);
Mode& assert_value_exists(std::map<Key_Type, Mode> const& map_, Key_Type const& key) {
  auto it = map_.find(key);
  assert(it != map_.end());
  return it->second;
}

我认为这相当于我的目标。当map中存在键时初始化const变量,否则上升断言。

const auto it = modeMap.find(key);
assert(it != modeMap.end() && "Mode doesn't exist");
const Mode myMode = it->second;

我同意这里所有的答案,断言本身不是一个好的解决方案。在生产环境中,当禁用assert且值不在映射中时,这是很危险的。正如@Jens提到的,最好抛出一个异常,或者终止你的程序。(所以推荐其他答案)。

从防御性编程的角度来看,请不要认为这个答案是最好的方法。

这是对使用map中的值初始化const变量,如果map中不包含这样的键,则使用assert的问题的回答。

EDITED:正如@cad指出的链接

Assert宏被设计用来捕获编程错误,而不是用户或运行时错误,因为它通常在程序退出调试阶段后被禁用。

编辑:还想引用@Joachim Pileborg

"使用assert不适合运行时检查。首先,它会中止程序,它会看起来像崩溃,这对他人使用的任何一种程序。其次,它是一个只用于调试的宏,如果创建一个发布版本,assert宏将被替换为空空间。只要你记得这是一个宏观将在发布版本中被空白替换(这可能会导致语法错误(取决于使用它的位置)。"