悬挂 if 和宏

dangling if and macro

我需要摆脱警告,其中之一是 -Wdangling-else。它在以下宏定义中记录了一个悬空 if:

#define FOR_EACH_REF(var, container) \
    if(bool _cont = true) \
      for(our::remove_reference<decltype(container)>::type::iterator _it = (container).begin(); _it != (container).end() && _cont; ++_it) \
        if((_cont = false)) {} else \
          for(our::remove_reference<decltype(container)>::type::value_type& var = *_it; !_cont; _cont = true)

我必须承认,我并没有真正了解这个宏,因此不知道如何解决这个警告。

谁能帮我解释一下如何避免 else 悬空?

how to avoid the dangling else?

最简单(但不推荐)的选项是使用 -Wno-dangling-else 在编译器中禁用警告。

真正的解决方案是在 if/else 分支周围添加大括号:

#define FOR_EACH_REF(var, container) \
    if(bool _cont = true) { \
    for(/* ... */) \
        if((_cont = false)) {} else { \
        for(/* ... */)

#define FOR_EACH_REF_END }}

用法:

FOR_EACH_REF(foo, bar) 
{ 

}
FOR_EACH_REF_END

如果你想迭代一个范围,C++11 提供了相应的语言语法,应该使用它来代替这个可恶的宏:

for(const auto& var : container) { }

您可以反转条件以避免出现空的 if 块并因此出现问题 else:

#define FOR_EACH_REF(var, container) \
    if (bool _cont = true) \
      for(our::remove_reference<decltype(container)>::type::iterator _it = (container).begin(); _it != (container).end() && _cont; ++_it) \
        if(!(_cont = false)) \
          for(our::remove_reference<decltype(container)>::type::value_type& var = *_it; !_cont; _cont = true)

从 C++11 开始,甚至可以很容易地编写:

#define FOR_EACH_REF(var, container) for (auto& var : container)