在条件中使用boost :: tribool时,它是编译器错误还是我的错误?

时间:2014-12-01 19:16:56

标签: c++

代码如下: (Coliru Code

#include <stdlib.h>
#include <iostream>
#include <iomanip>
#include <boost/logic/tribool.hpp>

struct B
{
  boost::tribool boo;

  void bug ()
  {
    bool tmp = indeterminate (boo);
    std::cout << "tmp = " << std::boolalpha << tmp << "\n";
    if (tmp && (boo = should_not_be_called ()) == false) {;}
  }

  bool should_not_be_called () const
  {
    std::cout << "BUG, wrong call\n";
    abort ();
  }
};

int main ()
{
  B a;
  a.bug ();
}

输出

tmp = false
BUG, wrong call
bash: line 7: 14410 Aborted                 (core dumped) ./a.out

我无法理解为什么在这里调用should_not_be_called。测试的编译器是gcc 4.9和clang 3.6。

更新:

我阅读了答案并用&#34更改了行;如果&#34;到

if (tmp && (false == (boo = should_not_be_called ()))) {;}

Coliru

现在&amp;&amp;&amp;&amp;运营商,但我仍然有同样的错误。为什么呢?

2 个答案:

答案 0 :(得分:15)

编译器在右边。让我们分析两个if中涉及的类型,并考虑所有operator overloads that boost::tribool provides

if (tmp && (boo = should_not_be_called ()) == false) {;}

if (bool && (tribool = bool) == bool) {;} // = is overloaded to return tribool
if (bool && tribool == bool) {;} // == is overloaded to return tribool
if (bool && tribool) {;} // && is overloaded

第二个if

if (tmp && (false == (boo = should_not_be_called ()))) {;}

if (bool && (bool == (tribool = bool))) {;} // = is overloaded to return tribool
if (bool && (bool == tribool)) {;} // == is overloaded to return tribool
if (bool && tribool) {;} // && is overloaded

在这两种情况下,我们最终都会出现重载operator &&。运算符重载是不考虑内置运算符的特殊调用行为的函数。也就是说,用户重载&&||执行短路,,的用户重载保证操作数评估顺序。所有三个都以未指定的顺序评估所有操作数,就像任何其他函数调用一样。

这正是强烈建议不要超载&&||,的原因,如果您希望它们意味着“和”,“或”等“序列”。


摘录问题原文:

编译器在右边。 boost::tribool重载opeator !,这意味着&&的操作数类型为boolboost::triboolboost::tribool也会为这些参数类型重载operator &&,因此会调用此重载。

答案 1 :(得分:4)

boost :: tribool中的逻辑运算符如上所述HERE重载,因此与c ++的内置逻辑运算符不同,逻辑运算符的从左到右的评估不适用且没有短路因此评估操作数仍未指定。