2014-08-29 18 views
13

Il seguente codice genera avviso C4127 (espressione condizionale è costante) in Visual Studio 2010 (dove alias_wchar_t è un alias per wchar_t):C4127: espressione condizionale è costante

if (sizeof(alias_wchar_t) == sizeof(wchar_t)) // warning occurs here 
{ 
    // do stuff 
} 
else 
{ 
    // do other stuff 
} 

Qual è il modo più elegante per risolvere questo , a corto di sopprimere l'avvertimento?

La soluzione migliore che ho trovato è quella di inserire il condizionale in un bool statico e usarlo come condizione. C'è una buona quantità di codice di sopra e al di sotto del if-else, così ho avvolgere il tutto in parentesi graffe per limitare l'ambito della variabile il più possibile:

// <snip> 

{ 
    static bool isSameSize = (sizeof(alias_wchar_t) == sizeof(wchar_t)); 
    if (isSameSize) 
    { 
     // do stuff 
    } 
    else 
    { 
     // do other stuff 
    } 
} 

// <snip> 

questo si sente piuttosto grossolano però. Sembra che dovrebbe essere risolvibile in fase di compilazione piuttosto che in runtime, ma il preprocessore non conosce la dimensione di. C'è un modo più pulito, più elegante per risolvere questo?

+1

nota: C++ 17 sta prendendo in considerazione qualcosa di simile a 'se constexpr' che risolverebbe questo problema –

risposta

5

Sembra che tu sappia cosa sta succedendo, e tu stai bene con questo.

compilatore pragma s sono pensati per casi del genere:

__pragma(warning(push)) 
__pragma(warning(disable:4127)) 
if (sizeof(alias_wchar_t) == sizeof(wchar_t)) { 
__pragma(warning(pop)) 
} 

In sostanza, si indica il compilatore (e ancora più importante, per i lettori umani del codice) che hai recensito l'avvertimento, e che Sai cosa stai facendo.

+4

Personalmente penso che la soluzione originale di Christopher Berman è meglio. I pragma sono specifici del compilatore ed eccessivamente prolissi. –

2

Questo è quello che ho messo a punto. Non causa alcun avviso in Microsoft Visual Studio 2013 e non richiede l'utilizzo di Pragmas specifici di Visual C++.

Prima definire la seguente classe modello.

template <bool b> 
struct condition 
{ 
    static bool test() 
    { 
     return true; 
    } 
}; 
template <> 
struct condition<false> 
{ 
    static bool test() 
    { 
     return false; 
    } 
}; 

quindi utilizzarlo come segue.

if (condition<sizeof(alias_wchar_t) == sizeof(wchar_t)>::test()) 

ho avuto l'idea dal C++ 14 std :: condizionale descritto http://en.cppreference.com/w/cpp/types/conditional.

5

Qual è il modo più elegante per risolvere questo, a corto di sopprimere l'avviso ?

La condizione è nota al momento della compilazione, in modo da poter effettuare il controllo in fase di compilazione, anche. Non utilizzare uno if, lasciare semplicemente che il compilatore inserisca una chiamata alla funzione corretta. Ecco un esempio completo:

#include <iostream> 

typedef short alias_wchar_t; // for testing 

template<bool Condition> 
struct DoStuff 
{ 
}; 

template<> 
struct DoStuff<true> 
{ 
    static void doStuff() 
    { 
     std::cout << "sizeof(alias_wchar_t) == sizeof(wchar_t)\n"; 
    } 
}; 

template<> 
struct DoStuff<false> 
{ 
    static void doStuff() 
    { 
     std::cout << "sizeof(alias_wchar_t) != sizeof(wchar_t)\n"; 
    } 
}; 

void doStuff() 
{ 
    DoStuff<sizeof(alias_wchar_t) == sizeof(wchar_t)>::doStuff(); 
} 

int main() 
{ 
    doStuff(); 
} 

Se questo è davvero più elegante di quanto il tuo codice originale (con appena quel particolare avviso del compilatore spento per questa unità di compilazione) è opinione basata, direi.

In ogni caso, questo compila con nessun avviso a /W4 con VC 2013.

+0

Non pensi che hai appena raddoppiato la quantità di codice per mantenere;) –

+0

@AlexanderEnaldiev: lunghezza codice non è l'unico fattore nel determinare quanto facilmente qualcosa può essere mantenuta. Come ho detto qui più di due anni fa, se è più elegante o meno dipende dal contesto reale del codice. –

+0

Non posso essere d'accordo con te. Potrebbe essere inutile. Diciamo template struct Foo {bool Check() { bool retval = checkImpl(); se (rigoroso) retval = retval && checkStrict(); retval di ritorno; } }; Per che cosa ho C4127 qui? Non pensi, sono abbastanza sicuro che la costante dipende dal modello arg? O qual è il punto di C4127. Cosa mostra? Non riesco a capire ancora. Indipendentemente dagli anni passati;) –

1

Se è solo un'espressione costante quindi utilizzare:

typedef wchar_t alias_wchar_t; 
bool constExpression = sizeof(alias_wchar_t) == sizeof(wchar_t); 
if (constExpression) // potential warning 
{ 
    // do stuff 
} 
else 
{ 
    // do other stuff 
} 

Sembra che il c4127 è generato dal mero azione di valutare un'espressione costante nella dichiarazione di controllo.

+0

Ho usato una variante di questo con successo: constexpr bool constExpression = sizeof (alias_wchar_t) == sizeof (wchar_t); if (constExpression) {} –

3

Un altro modo per disattivare l'avviso è quello di creare una funzione di un'identità fittizia e usarlo su una delle costanti.

// Define this somewhere 
template<typename T> const T& identity(const T& t) { return t; } 

... 

// NB: 'identity' used only to remove "warning C4127" 
if (identity(sizeof(alias_wchar_t)) == sizeof(wchar_t)) 
{ 
    // do stuff 
} 
else 
{ 
    // do other stuff 
} 

Questo non è perfetto, ma sembra più leggero rispetto ad altre soluzioni e riutilizzabile per vari tipi di costanti.

Problemi correlati