【问题标题】:C++ !! conversion to boolC++!!转换为布尔值
【发布时间】:2011-12-26 20:57:06
【问题描述】:

在 C++ 中有一个构造 !! 适用于非布尔值以将其转换为布尔值。例如:

int n = 12;

if ( !!n )
  std::<<cout << "n is true";
else
  std::<<cout << "n is false";

在哪些地方可以应用,或者哪些类型适用:POD、指针等有什么限制吗?

【问题讨论】:

标签: c++ if-statement conditional-statements


【解决方案1】:

限制是必须为该类型定义operator!(并且它必须产生一个还定义了operator! 的类型)

【讨论】:

  • 所以让我们尝试指定类型: 1) POD (int, long, etc); 2)指针? 3) 任何支持运算符的自定义类! ?
  • @Denis:以下类型是 POD,但不适用于 !!struct a { int b; };。以下类型是 POD,并且确实有效:bool。所以 POD 在这里不是一个有用的分类。
【解决方案2】:

它适用于任何可以在布尔上下文中求值的类型。所以算术类型、指针类型(包括指向(成员)(函数)的指针)以及任何可以转换为其中之一的东西。加上枚举类型、std::nullptr_t 之类的零碎东西,可能还有我忘记的其他东西。 C++11 中的 4/3 定义了 contextually convert to bool 的含义,这就是内置的operator! 所做的。

对于所有这些类型,写if(!!n) 是多余的,你可以写if(n) 具有相同的含义。此类类型的!!nbool(n)static_cast&lt;bool&gt;(n); 的含义相同。

它也适用于任何具有重载 operator! 的类型,该类型返回可转换为 bool 的类型(或返回具有 operator! 重载以返回 bool 的类型)。

如果最左边的 operator! 返回 bool 以外的类型,那么您可能仍然可以编写 if(!!n),但 !! 不能转换为 bool。它充当对返回的任何类型的转换。

【讨论】:

  • 我实际上将!! 称为反模式。如果一个对象转换为bool 或类似的东西(很少应该),那么直接将它用作bool。如果不支持,它也不应该支持!。大多数时候,最好明确说明您正在测试什么:someInt == 0(而不是!!someInt),或!someObj.isValid(),而不是!!someObj,甚至someObj
  • 我认为最后一段是错误的。如果!n 不是bool(因为公然滥用运算符重载),那么!!n 将在!n 返回的任何类型上调用!。而对于所有非用户定义的类型,如果! 是合法的,那么结果就是bool
  • @James:“如果不支持,它也不应该支持!” - 我想我同意,我只是不确定自己是否可以作为一项规则声明。我怀疑!! 最常用作 C89(或更早版本)代码的后遗症,其中当然没有布尔类型,!!n 是映射整数 0->0 和其他任何东西 ->1 的惯用语,并且可能用于像lookup_table[2*a + !!b];这样的复杂结构中。
  • @James:“外部”operator! 我指的是左边的那个。我在最后一段中想到的是A::operator! 返回B,而B::operator! 返回int。这是病态和扭曲的,但发问者要求对 !! 使用“任何限制”作为对 bool 的转换。这个假设的愚蠢定义给出的结果是if(!!a) 编译并做了一些可能有意义也可能没有意义的事情,但!!a 没有bool 类型。不过,您可以使用 !!!!aA 转换为 bool
【解决方案3】:

其他答案适合您的实际问题。

但是,如果您打算使用示例中的代码来“简化”您的代码(因为它使代码更短),我想我建议您不要这样做。相反,简化含义并检查整数是否为零而不是整数上的双重负数。

if (n!=0) 
    { 
      //whatever
    }

针对零进行显式测试具有独立于您是否记得 c++ 中使用的“零为假”约定的好处。请参阅https://stackoverflow.com/q/329582/498253,以及下面的 cmets。

这是因为对我来说,if(!!my_int) 不是很清楚——它的意图并不明显,在这一点上形成一个分支看起来会导致问题。

以前的sn-p(这样非常有用的cmets才有意义)

bool my_bool = (n != 0) ? true : false; //whichever way you want it to work.
if (my_bool) 
  { 
    //whatever
  }

【讨论】:

  • 我更喜欢你的风格来保持代码最明显。不过也有很多地方!!仍在使用。
  • 对于整数类型,这太荒谬了,只需写if(my_int)。您可以根据需要继续添加噪音:bool my_bool = !!((n!=0) ? true : false) ? true : !!false);,但这只是噪音。 C++ 程序员必须了解在 C++ 中,整数可以在布尔上下文中使用,这意味着什么,然后if(my_int) 是完全可读的,或者如果你真的不喜欢 int -> bool 转换,if(my_int != 0)!! 应该保留给不转换为 bool 但确实有 operator! 的类型,尽管有些人使用它来避免输入 (bool),或者在从 C89 迁移的代码中。
  • @SteveJessop:说得好。我会删除我的答案,但我认为您的评论很有用 - 所以它会保留
  • @Tom (n != 0) ? true : false 是一种反模式。 n != 0 有什么问题?
  • @SteveJessop 如果n 不是布尔值,那么只写if (n) 也会令人困惑。说出你的意思,说出你的意思:if ( n != 0 )(如果nint)。仅仅因为 C++ 支持数量惊人的隐式转换并不意味着您必须使用它们。
【解决方案4】:

唯一的限制是特定类型的对象应该可以转换为布尔或整数类型。

比如下一个类型不能转换:

struct A
{
  int a;
  float b;
};

但接下来可以:

struct B
{
  int v;
  operator int()
  {
    return v;
  }
};

【讨论】:

    【解决方案5】:

    !! 只是应用了两次的! 运算符。适用于所有可以使用!的表达式。

    编辑:

    运算符! 的重载实例被假定为逻辑not

    【讨论】:

    • 可以,但是定义一个不等同于逻辑not 的运算符! 并不是好的编程习惯。
    • 好吧,我从来没有说过好的编程实践;)
    • @KlasLindbäck:你听说过safe bool idiom 和/或std iostream吗?此外,Boost Proto 及其衍生作品(Expressive、Spirit)使用运算符!非常成功地返回了甚至不能转换为 bool 的东西
    猜你喜欢
    • 2011-03-22
    • 1970-01-01
    • 2021-06-27
    • 2018-01-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-28
    相关资源
    最近更新 更多