Il compilatore di Visual C++ avvisa della conversione in bool
, ma con un avviso di prestazione stupido. Di solito è un avvertimento indesiderato, ma sfortunatamente non può essere messo a tacere con un cast semplice. Il quasi-idioma per mettere a tacere è usare una doppia negazione, !!
, bang-bang, ad es. return !!0.0
.
Il tuo problema è il contrario, che tu vuoi un tale avvertimento o errore, ma comunque il quasi-idioma bang-bang può essere parte di una soluzione.
Con l'idea esemplificato qui sotto, è sufficiente scrivere Bool
invece di bool
in cui si desidera un valore booleano, e utilizzare il !!
per garantire pulite bool
valori, altrimenti si ottengono errori di compilazione.
La cosa bella di questo è che molto probabilmente è sufficiente effettuare una ricerca globale e sostituire il codice, sostituendo bool
con Bool
.
#ifdef CLEAN
# define TO_BOOL !!
#else
# define TO_BOOL
#endif
#define STATIC_ASSERT(e) static_assert(e, #e)
#include <type_traits> // std::is_same
#include <utility> // std::enable_if_t
class Bool
{
private:
bool value_;
public:
operator bool() const { return value_; }
template< class T
, class Enabled_ = std::enable_if_t<std::is_same<T,bool>::value, void>
>
auto operator=(T const other)
-> Bool&
{ value_ = other; return *this; }
Bool(): value_() {}
template< class T
, class Enabled_ = std::enable_if_t<std::is_same<T,bool>::value, void>
>
Bool(T const value)
: value_(value)
{}
};
auto f()
-> double
{ return 0.0; }
auto something()
-> Bool
{ return TO_BOOL 0.0; } // ← Line 43
auto g()
-> double
{
Bool x = TO_BOOL 0.0; // ← Line 48
if (something()) {
x = TO_BOOL f(); // where f() is a function returning a double
}
return x;
}
auto main() -> int
{
Bool a, b, c;
return a && b || something();
}
compilation di esempio con g ++:
c:\my\forums\so\105> g++ foo.cpp
foo.cpp: In function 'Bool something()':
foo.cpp:43:22: error: could not convert '0.0' from 'double' to 'Bool'
{ return TO_BOOL 0.0; } // ← Line 43
^
foo.cpp: In function 'double g()':
foo.cpp:48:25: error: conversion from 'double' to non-scalar type 'Bool' requested
Bool x = TO_BOOL 0.0; // ← Line 48
^
foo.cpp:50:13: error: no match for 'operator=' (operand types are 'Bool' and 'double')
x = TO_BOOL f(); // where f() is a function returning a double
^
foo.cpp:23:14: note: candidate: template<class T, class Enabled_> Bool& Bool::operator=(T)
auto operator=(T const other)
^
foo.cpp:23:14: note: template argument deduction/substitution failed:
foo.cpp:12:11: note: candidate: Bool& Bool::operator=(const Bool&)
class Bool
^
foo.cpp:12:11: note: no known conversion for argument 1 from 'double' to 'const Bool&'
foo.cpp:12:11: note: candidate: Bool& Bool::operator=(Bool&&)
foo.cpp:12:11: note: no known conversion for argument 1 from 'double' to 'Bool&&'
foo.cpp: In function 'int main()':
foo.cpp:58:18: warning: suggest parentheses around '&&' within '||' [-Wparentheses]
return a && b || something();
^
c:\my\forums\so\105> g++ foo.cpp -D CLEAN
foo.cpp: In function 'int main()':
foo.cpp:58:18: warning: suggest parentheses around '&&' within '||' [-Wparentheses]
return a && b || something();
^
c:\my\forums\so\105> g++ foo.cpp -D CLEAN -Wno-parentheses
c:\my\forums\so\105> _
Se volete conversione implicita da Bool
a qualche altro tipo di bool
non devono essere considerati, semplicemente fanno anche che il responsabile della conversione di un modello selezionato, come il costruttore e operatore di assegnazione.
Hai provato '-pedantic-errors'? –
Ho appena provato con: g ++ -Wall -Wextra -pedantic-errors -c dummy.cpp e non ho ancora avvertimenti. – Renaud
MSVC 14 genera [C4800] (https://msdn.microsoft.com/en-us/library/b6801kcy.aspx) per questo. – wally