没有选择语句的C ++条件

时间:2016-04-12 15:44:02

标签: c++ if-statement expression logical-operators

也许是因为Perl的影响,我喜欢使用以下语法

condition && do_something();

而不是

if ( condition )
{
  do_something();
}

(我知道我可以将后者排成一行而没有括号,但这不是重点。)

我做了几次测试(下面),这是有效的。 但我在标准中找不到参考,说它是合法的。 可以隐含在

  • 5.14逻辑AND运算符
  • 5.17分配操作员
  • 6.4。选择陈述

但我不完全确定(我检查了C ++ 98,很抱歉老式,但即使是C标准就足够了)。

注意:我确实意识到为了工作,最后一个表达式(do_something)也必须可以转换为bool,这对于选择语句来说不是必需的。这当然是一个严重的限制。

所以问题是:

  1. 完全合法吗?
  2. 有没有理由不使用它?
  3. 是否存在可能的副作用(如导致意外结果的优化)?
  4. 道歉如果证明是重复的,我找不到任何东西,但可能是因为我没有使用正确的关键词。

    #include <cassert>
    
    bool sayYes()
    {
      return true;
    }
    
    bool sayNo()
    {
      return false;
    }
    
    int main( int args, char* argv[] )
    {
      bool a = true;
      bool b = false;
      int i = 0;
    
      a && ( i = 1 );
      assert( i == 1 );
    
      !a && ( i = 0 );
      assert( i == 1 );
    
      ( a || b ) && ( i = 0 );
      assert( i == 0 );
    
      sayYes() && ( i = 1 );
      assert( i == 1 );
    
      ( sayNo() || sayYes() ) && ( i = 0 );
      assert( i == 0 );
    
      return 0;
    }
    

4 个答案:

答案 0 :(得分:4)

这完全合法。来自[expr.log.and]:

  

&&保证从左到右   评估:如果第一个操作数为false,则不评估第二个操作数。

expr() && fun()相当于if (expr()) fun()(假设fun()返回可转换为bool的内容)。在编写复合条件表达式时,这是一个非常重要的属性。例如,只有在我们知道指针有效后才解除引用指针:

if (ptr && ptr->foo()) { ... }

那就是说,如果你真正想要的是:

if (expr()) {
    fun();
}

写下来。编译器将以任何一种方式生成相同的代码,但您尝试执行的操作的目的将更加清晰。

答案 1 :(得分:3)

  1. 是的,这是合法的。后跟;的表达式是有效的陈述。

  2. 有些人可能会觉得它很混乱。

  3. 如果有副作用,则无法优化。

  4. 请注意,虽然在C ++中&&可能重载。如果它超载,则丢弃操作员的短切属性。 会造成奇怪的效果。主要是因为这个原因,我会反对这种风格。

答案 2 :(得分:3)

我认为我有义务指出这一点。 你应该不惜一切代价避免你想要做的事情。你试图操纵语言本身的语法太模仿另一个人的语法。而且你这样做是因为你对使用 if语句的另一种语法感到更舒服。你不能这样想,有一次这个代码会被其他人看到,当他们看到这种奇怪的语法时,他们会完全混淆。如果我在任何c ++库中看到我将要使用的东西,我就不会使用它而再也不用担心它了。

也许你决定用camel case命名所有变量,或者你认为你应该在privateprotectedpublic说明符之前省略填充的空格,或者也许你只是想把所有的括号放在一个新的行上。那时你应该说:

  

...我喜欢使用以下内容......

但是当你决定不喜欢语言如何读取if-statement或函数声明时,你必须处理它。为什么?因为它是如何完成的,那就是语言的编写方式。您尝试做的事情相当于更改英文字母的字母,因为您对“英语字母表”的使用方式更加满意。看你的母语。

每当我看到&&时,我认为有三件事之一,r-valueuniversal refAND。我是否想到if?没有。我为什么要说我以前用Perl编程,嘿,你怎么知道我是否熟悉这样的语法?

所以基本上......

你用c ++写作,你不是用Perl写的。 在某些地方,您将不得不用不同的语言编写,那么您是否会尝试操纵它的语法?你甚至可以做这样的事情,它从哪里开始,它停在哪里?

答案 3 :(得分:1)

我必须承认我使用这种技术,因为它经常看起来更简洁(至少对我和我的同事来说)与其他操作符表示相结合。

考虑这个(人为的但是指示性的)例子:

#include <string>
#include <stdexcept>
#include <exception>
#include <regex>

struct invalid_number : std::logic_error
{
    using std::logic_error::logic_error;
};

template<class Excep, class...Args>
[[noreturn]]
bool raise(Args&&...args)
{
  throw Excep(std::forward<Args>(args)...);
}

int parse_number(const std::string& s)
try
{
  const std::regex re("^\\d+$");
  std::regex_match(s, re) or raise<std::invalid_argument>(s);
  return std::stoi(s);
}
catch(...)
{
  std::throw_with_nested(std::invalid_argument(__func__));
}