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
Выход:
Исходный код:
#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 должен по праву предупреждать вас об этом; от их собственного документация:
Следующие правила применяются ко второму и третьему выражению: Если оба выражения относятся к одному и тому же типу, результат будет того же типа. Если оба выражения имеют арифметический или перечислимый типы, обычные арифметические преобразования (описанные в арифметических преобразованиях) выполняются для преобразования их в общий тип. Если оба выражения имеют тип указателя или если одно является типом указателя а другое является константным выражением, которое оценивается в 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 );
...
Других решений пока нет …