C ++ Boost Трибунал Тернарный оператор неверное значение

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

Мораль истории: compiler выбирает TYPES на основе VALUES.

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

Выход:

  1. undet: 1? неопределенный: ложный
  2. undet: 0? неопределенный: ложный
  3. правда: 1? неопределенный: правда
  4. правда: 0? неопределенный: правда
  5. undet: 1? неопределенный: трибоул (ложь)
  6. ложь: 0? неопределенный: трибоул (ложь)
  7. undet: 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;
}

2

Решение

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

Следующие правила применяются ко второму и третьему выражению:

Если оба выражения относятся к одному и тому же типу, результат будет того же типа.

Если оба выражения имеют арифметический или перечислимый типы,
обычные арифметические преобразования (описанные в арифметических преобразованиях)
выполняются для преобразования их в общий тип.

Если оба выражения имеют тип указателя или если одно является типом указателя
а другое является константным выражением, которое оценивается в 0,
Преобразование указателя выполняется для преобразования их в общий тип.

Если оба выражения имеют ссылочные типы, ссылочные преобразования
выполняются для преобразования их в общий тип.

Если оба выражения имеют тип void, общий тип имеет тип void.

Если оба выражения имеют заданный тип класса, общий тип
этот тип класса.

Любые комбинации второго и третьего операндов, не указанные в предыдущем
Список незаконен. Тип результата является общим типом, и это
значение l, если второй и третий операнды имеют одинаковый тип
и оба являются l-значениями.

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

Если оба выражения имеют тип указателя или если одно является типом указателя
а другое является константным выражением, которое оценивается в 0,
Преобразование указателя выполняется для преобразования их в общий тип.

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

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 );
...
3

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]