Тройной оператор C++ Boost Tribool неправильное значение
Вопрос
Boost 1.55, MSVC экспресс 2012.Неправильная оценка выражения с помощью трибула.Это работает правильно только тогда, когда я явно указываю tribool(false).
Мораль истории:компилятор выбирает ТИПЫ на основе ЗНАЧЕНИЙ.
auto a = 0? indeterminate : false; // type function pointer
auto b = 0? indeterminate : true; // type bool
Выход:
- индет:1?неопределенный:ЛОЖЬ
- индет:0?неопределенный:ЛОЖЬ
- истинный :1?неопределенный:истинный
- истинный :0?неопределенный:истинный
- индет:1?неопределенный:трибул (ложь)
- ЛОЖЬ :0?неопределенный:трибул (ложь)
- индет:1?неопределенный:трибул (правда)
- истинный :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 );
...