2011-01-14 7 views
2

Ich habe eine Art T, und in einigen Fällen kann es, zum Beispiel char, aber ich möchte seinen Integralwert, nicht das Zeichen ausgeben. Dazu ist haben die folgenden:Casting zu int oder float je nach is_integer

typedef (std::numeric_limits<T>::is_integer ? int : float) FormatType; 
os << static_cast<FormatType>(t); 

jedoch, dies zu kompilieren schlägt fehl, die besagt, „error C2275: 'int' : illegal use of this type as an expression“. Prefixing int und float mit typename dreht sich nicht um das Problem. Was fehlt mir hier?

Die folgenden, die ich glaube, äquivalent ist, funktioniert:

if(std::numeric_limits<T>::is_integer) 
{ 
    os << static_cast<int>(t); 
} 
else 
{ 
    os << static_cast<float>(t); 
} 
+0

Ist das 'C++ 0x'? – Troubadour

+0

@Troubadour: Nein – dukedave

+1

Übrigens wäre es gleichbedeutend mit der Tatsache, dass ersteres nicht gültig ist. :) –

Antwort

3

Was fehlt mir hier?

Sie versuchen, Typen als Ausdrücke zu verwenden. C++ lässt dies einfach nicht zu. Sie können stattdessen über Metaprogrammierung die sogenannte "Kompilierzeit if" verwenden. Zum Beispiel, ich glaube Boost-folgendes bietet:

typedef if_<std::numeric_limits<T>::is_integer, int, double>::type FormatType; 

os << static_cast<FormatType>(t); 

Auf der anderen Hand, Ihre zweite Lösung funktioniert gut, und der Compiler wird herausfinden, dass einer des Zweiges nie wahr sein kann, und es zu beseitigen. Die Leistung wird also in beiden Fällen gleich sein (tatsächlich sollte der exakt gleiche Code generiert werden).

2

Versuchen ganzheitliche Förderung mit:

os << +t; 

Sie werden eine int aus ihm heraus für einen integralen Typ erhalten, oder Ihre ursprünglicher Gleitkommatyp, wenn es einer war.

+0

Zu obskur zu verwenden, wie es ist, IMHO. Ich würde es in eine richtig benannte Funktion kapseln, um die Absicht zu verdeutlichen. Ansonsten sehr elegant. –

+0

@Konrad: Ihre Funktion müsste templated sein, und ich denke, wir wären wieder da, wo wir mit der ursprünglichen Frage angefangen haben. Ich sehe nicht, dass es obskur ist, obwohl ein kleiner Kommentar neben seiner Verwendung keine schlechte Idee sein könnte. –

+0

@Tomak: Ich habe die Antwort von Konrad akzeptiert, weil es direkt die Frage adressiert, aber ich habe tatsächlich Ihren Ansatz in meinem Code verwendet, also wünschte ich, ich könnte mehr als +1 geben; und ich habe einen Kommentar hinzugefügt, um das Wissen weiterzugeben :) – dukedave

0

gcc akzeptiert es, nicht über andere sicher:

template<bool Expression, typename TrueResult, typename FalseResult> 
    class conditional_type; 

template<typename TrueResult, typename FalseResult> 
class conditional_type<1, TrueResult, FalseResult> { 
public: 
    typedef TrueResult R; 
}; 

template<typename TrueResult, typename FalseResult> 
class conditional_type<0, TrueResult, FalseResult> { 
public: 
    typedef FalseResult R; 
}; 

typedef conditional_type<std::numeric_limits<T>::is_integer,int,float>::R FormatType; 
+0

Dies ist ziemlich Standard-Template-Spezialisierung, alle halbwegs modernen Compiler akzeptieren dies. Warum benutzt du '1' und' 0' anstelle von 'true' und' false'? –

+0

@Konrad das ist nur, wie ich schreibe. Prost – justin

+0

@Justin: Ich sehe das. Die Frage ist, warum die Tatsache missbrauchen, dass C++ ein schwaches System hat? –