Тройной оператор C++ Boost Tribool неправильное значение

StackOverflow https://stackoverflow.com//questions/21061745

  •  26-12-2019
  •  | 
  •  

Вопрос

Boost 1.55, MSVC экспресс 2012.Неправильная оценка выражения с помощью трибула.Это работает правильно только тогда, когда я явно указываю tribool(false).

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

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

Выход:

  1. индет:1?неопределенный:ЛОЖЬ
  2. индет:0?неопределенный:ЛОЖЬ
  3. истинный :1?неопределенный:истинный
  4. истинный :0?неопределенный:истинный
  5. индет:1?неопределенный:трибул (ложь)
  6. ЛОЖЬ :0?неопределенный:трибул (ложь)
  7. индет:1?неопределенный:трибул (правда)
  8. истинный :0?неопределенный:трибул (правда)

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

#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;
}
Это было полезно?

Решение

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

 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.

Что соответствует,

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

определение в трибул.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 );
...
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top