【问题标题】:Why is this cast to bool required?为什么需要强制转换为布尔值?
【发布时间】:2014-03-16 20:49:47
【问题描述】:
template<typename InputIterator, typename Predicate>
inline InputIterator
find_if(InputIterator first, InputIterator last, Predicate pred, input_iterator_tag)
{
    while (first != last && !bool(pred(*first)))
         ++first;

    return first;
}

我在 GCC 4.7.0 附带的 C++ 标准库实现的源代码中遇到了this snippet。这是输入迭代器的find_if 的特化。我清理了前导下划线以使其更具可读性。

他们为什么在谓词上使用bool 强制转换?

【问题讨论】:

    标签: c++ gcc casting standard-library


    【解决方案1】:

    原因是只写!pred(*first) 可能会导致调用重载的operator! 而不是调用explicit operator bool

    有趣的是,这个措施是针对pred 进行的,但是在提供的实现中仍然可以选择重载的operator&amp;&amp;first != last 需要更改为 bool(first != last) 以防止这种过载。

    【讨论】:

    • 我认为如果operator&amp;&amp; 被重载,则由于在最后一次迭代中取消引用结束迭代器(没有短路),行为将是未定义的。所以也许实现可以随意忽略这个问题。
    • 为什么不说static_cast&lt;bool&gt;呢?为什么要强制转换?
    • @Mehrdad 他们在这种情况下做同样的事情,因为reinterpret_cast 从未被选中。 (而且 GCC 源代码只有 80 列宽。)
    • @JohannesSchaub-litb:但这不是说 && 一开始就不应该使用吗?
    • @Mehrdad 我对这个问题一无所知,我只是在没有任何教育的情况下进行了一些猜测
    【解决方案2】:

    标准只要求谓词在 可以转换为bool 的上下文。想必, “谓词”对象可以有一个operator bool 函数, 做了正确的事,还有一个 operator! 函数 完全不相关的东西。 (当然,那将是可怕的 设计,但标准要求库作为 指定,不管用户代码有多糟糕。)所以 g++ 转换为bool,然后在结果上使用! 转换(只有内置运算符可以应用)。

    【讨论】:

      【解决方案3】:

      在 C++ 标准中,相对于谓词

      换句话说,如果一个算法将 Predicate pred 作为它的参数 首先作为它的迭代器参数,它应该在 构造 pred(*first) 上下文转换为 bool

      “上下文转换为 bool”一词的意思是,即使一个类定义了一个将类的对象转换为 bool 的转换函数作为显式运算符,它也应该被应用。考虑一个上下文转换为 bool 的示例

      #include <iostream>
      
      struct A
      {
         explicit operator bool () const { return true; }
      };
      
      int main()
      {
         if ( A() ) 
         {
            std::cout << "Here is a contextual conversion to bool" << std::endl;
         }
      }
      

      所以在 C++ 标准引用的上下文中,我认为写表达式没有任何意义

      first != last && !bool( pred(*first ) )
      

      写就够了

      first != last && !pred(*first )
      

      这里 pred 被上下文转换为 bool。

      【讨论】:

      • 根据上下文转换为“bool”,这是用户定义的转换。但正如其他人在评论中所说,如果有operator!,那将是首选。这似乎是一个很好的评论。
      • @Johannes Schaub - litb 那么有一个问题。如果一个类没有定义转换运算符为 bool 但定义了运算符 !那么原始条件将发出错误。所以一些实现会用 operator 编译!而其他人则不会。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-08
      • 1970-01-01
      • 2012-04-12
      • 2015-01-29
      • 2018-07-18
      • 2021-05-21
      相关资源
      最近更新 更多