C++-Boost-Tribool-Ternäroperator falscher Wert
Frage
Boost 1.55, MSVC Express 2012.Falsche Ausdrucksauswertung mit Tribool.Es funktioniert nur dann korrekt, wenn ich tribool(false) explizit spezifiziere.
Moral der Geschichte:Der Compiler wählt TYPEN basierend auf WERTEN aus.
auto a = 0? indeterminate : false; // type function pointer
auto b = 0? indeterminate : true; // type bool
Ausgabe:
- Einzug:1?unbestimmt:FALSCH
- Einzug:0?unbestimmt:FALSCH
- WAHR :1?unbestimmt:WAHR
- WAHR :0?unbestimmt:WAHR
- Einzug:1?unbestimmt:tribool(falsch)
- FALSCH :0?unbestimmt:tribool(falsch)
- Einzug:1?unbestimmt:tribool(wahr)
- WAHR :0?unbestimmt:tribool(wahr)
Quellcode:
#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;
}
Lösung
Dabei handelt es sich um unterschiedliche Typen, und MSVC sollte Sie zu Recht davor warnen.von ihren eigenen Dokumentation:
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.
Da Ihr ternärer Operator für die Kombination von bool und unbestimmt nicht denselben Typ zurückgibt, wird das Ergebnis einer Konvertierung unterzogen, die wahrscheinlich mit dem übereinstimmt
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.
Welches entspricht dem,
typedef bool (*indeterminate_keyword_t)(tribool, detail::indeterminate_t);
Definition in tribool.hpp.Es ist dieser Funktionszeiger, der anstelle des „ausgewertet“ wird false
Wert.
Sie müssen also das haben ?
Der Operator gibt denselben Typ zurück.Ändern Sie Ihre Makros so, dass sie wie folgt aussehen:
TEST_TRIBOOL( 1 ? tribool(indeterminate) : tribool(false));
oder alternativ,
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 );
...