2014-01-11 4 views
2

Boost 1.55, MSVC express 2012. Неверная оценка выражения с помощью трибуны. Он работает корректно только тогда, когда я указываю dictool (false) явно.C++ boost tribool trernary operator неверное значение

Мораль истории: компилятор выбирает ТИПЫ на основе ЦЕННОСТЕЙ.

auto a = 0? indeterminate : false; // type function pointer 
auto b = 0? indeterminate : true; // type bool 

Выход:

  1. indet: 1? неопределенный: false
  2. номер: 0? неопределенный: false
  3. true: 1? неопределенный: true
  4. true: 0? неопределенный: true
  5. indet: 1? неопределенный: tribool (false)
  6. false: 0? неопределенный: tribool (false)
  7. indet: 1? неопределенный: tribool (true)
  8. true: 0? неопределенный: tribool (истина)

Исходный код:

#include <iostream> 
#include <boost/logic/tribool.hpp> 

using namespace boost; 

void test_tribool(const tribool& v, const char* name) 
{ 
    const char* s; 
    if (v) 
     s = "true"; 
    else if (!v) 
     s = "false"; 
    else 
     s = "indet"; 
    std::cout << s << "\t: " << name << std::endl; 
} 

#define TEST_TRIBOOL(...) test_tribool((__VA_ARGS__), #__VA_ARGS__); 

int main(int argc, char** argv) 
{ 
    TEST_TRIBOOL(1? indeterminate : false); 
    TEST_TRIBOOL(0? indeterminate : false); 

    // warning C4305: ':' : truncation from 'bool (__cdecl *)(boost::logic::tribool,boost::logic::detail::indeterminate_t)' to 'bool' 
    TEST_TRIBOOL(1? indeterminate : true); 

    // warning C4305: ':' : truncation from 'bool (__cdecl *)(boost::logic::tribool,boost::logic::detail::indeterminate_t)' to 'bool' 
    TEST_TRIBOOL(0? indeterminate : true); 


    TEST_TRIBOOL(1? indeterminate : tribool(false)); 
    TEST_TRIBOOL(0? indeterminate : tribool(false)); 
    TEST_TRIBOOL(1? indeterminate : tribool(true)); 
    TEST_TRIBOOL(0? indeterminate : tribool(true)); 

    return 0; 
} 
+2

Что * точно * бывает, что вы не ожидали? Вам нужен такой код, чтобы продемонстрировать его? И почему ваш макрос использует '...', если он работает только с одним аргументом? –

+1

Вы понимаете, что в 'a? b: c', 'b' и' c' должны иметь один и тот же тип, и компилятор рассказал вам, каким образом он разрешил конфликт в вашем коде, да? –

+0

Я могу сделать работу с кодом, но мне просто интересно, почему (2) является тем, чем он является. Как это возможно? Я использую ... в макросе, потому что он универсален. –

ответ

3

Это разные типы и MSVC должны быть по праву дают вам предупреждение об этом; от их собственных documentation:

 
The following rules apply to the second and third expressions: 

    If both expressions are of the same type, the result is of that type. 

    If both expressions are of arithmetic or enumeration types, 
    the usual arithmetic conversions (covered in Arithmetic Conversions) 
    are performed to convert them to a common type. 

    If both expressions are of pointer types or if one is a pointer type 
    and the other is a constant expression that evaluates to 0, 
    pointer conversions are performed to convert them to a common type. 

    If both expressions are of reference types, reference conversions 
    are performed to convert them to a common type. 

    If both expressions are of type void, the common type is type void. 

    If both expressions are of a given class type, the common type is 
    that class type. 

Any combinations of second and third operands not in the preceding 
list are illegal. The type of the result is the common type, and it is 
an l-value if both the second and third operands are of the same type 
and both are l-values. 

Поскольку ваша тройная оператор не возвращает тот же типа, для комбинации BOOL и неопределенной, результат претерпевает преобразование, которое, вероятно, соответствует

 
    If both expressions are of pointer types or if one is a pointer type 
    and the other is a constant expression that evaluates to 0, 
    pointer conversions are performed to convert them to a common type. 

, который соответствует a,

typedef bool (*indeterminate_keyword_t)(tribool, detail::indeterminate_t); 

определение в tribool.hpp. Это указатель функции, который «оценивается» вместо значения false.

Таким образом, вы должны вернуть оператору ? тот же тип. Измените макросы выглядеть следующим образом:

TEST_TRIBOOL(1 ? tribool(indeterminate) : tribool(false)); 

или в качестве альтернативы,

const tribool t_indet(indeterminate); 
const tribool t_false(false); 
const tribool t_true(true); 

TEST_TRIBOOL(1 ? t_indet : t_false); 
TEST_TRIBOOL(0 ? t_indet : t_false); 
... 
+0

Я знаю, КАК исправить, но ПОЧЕМУ он должен быть исправлен в случае (0? Indeterminate: false) == indet. Что именно происходит? –

+0

Я расширил свой ответ, надеюсь, что теперь это поможет. – mockinterface

+0

Я думаю, что bool отсылается к функции pointer == 0 - это ответ, спасибо! –

Смежные вопросы