T() oder static_cast<T>() ?
-
Hallo,
mal eine Frage bezüglich templates, angenommen ich hab so eine Funktion:
template <typename T> void foo(T t) { T value1 = T(1); // Variante 1 T value2 = static_cast<T>(1); // Variante 2 }
Welchen der beiden Varianten ist der Vorzug zu geben (und warum)?
Bis jetzt habe ich nämlich immer Variante 1 benutzt, da kürzer und ohne cast. Allerdings hab ich gesehen dass einige Funktionen in
boost
die zweite Variante benutzen und daher bin ich mir jetzt unsicher.Macht das überhaupt einen Unterschied oder ist es nur Geschmacksache?
-
Der functional-cast T() ist für primitive Typen mit dem C-Cast (T) identisch und kann daher mehr als ein static_cast, z.B. Pointer nach int und solche Scherze.
-
Welchen der beiden Varianten ist der Vorzug zu geben (und warum)?
Dass man eine Variable anders initialisiert ist dir hoffentlich klar.
Angenommen du müsstest einen Ausdruck in einen anderen Typ casten.
FürT(e)
(wobeie
ein Ausdruck ist) gelten die folgenden Regeln:[expr.type.conv]/1 schrieb:
If the expression list is a single expression, the type conversion expression is equivalent (in definedness, and if defined in meaning) to the corresponding cast expression (5.4).
Die "corresponding casting expression" ist einfach ein c-style Cast, also
(T)e
. Und ein solcher Cast ist zum ersten gültigen Cast in der folgenden Liste äquivalent:static_cast
static_cast
undconst_cast
reinterpret_cast
reinterpret_cast
undconst_cast
Daher ist
T(e)
allgemeiner alsstatic_cast<T>(e)
, es kann einenconst_cast
implizieren undreinterpret_cast
anwenden. Und das kann in Template-Code zu Problemen führen - aber auch nur wenn Zeiger im Spiel sind. SolangeT
ein Klassentyp oder ein arithmetischer Typ ist sind beide Formen äquivalent undT(...)
ist vorzuziehen. Und wenn mehrere Ausdrücke als Initializer dienen (bspw. für einen Konstruktoraufruf) kannst du nur functional-style casts verwenden. Wenn ich weiß dassT
arithmetisch ist schreibe ich natürlichT(1)
. Wozustatic_cast
? Ist dasselbe mit mehr Schreibaufwand.
-
Ich bevorzuge
static_cast<T>(u)
.
Warum: was Bashar geschrieben hat. Und da die "Macht" des C-Style Casts meist unerwünscht ist...
-
Arcoth schrieb:
Dass man eine Variable anders initialisiert ist dir hoffentlich klar.
Warum macht boost dann sowas?
const value_type a = static_cast<value_type> ( 1 ) / static_cast<value_type>( 2 );
Ich dachte T(x) ruft ganz normal (und ohne cast) den Konstruktor auf, wusste nicht dass das äquivalent tu (T)x ist... das ist natürlich blöd. Warum macht man denn hier so eine Ausnahme für "single expressions"?
-
Ich dachte T(x) ruft ganz normal (und ohne cast) den Konstruktor auf, wusste nicht dass das äquivalent tu (T)x ist
Ja, aber
(T)x
ist doch für Klassen äquivalent zustatic_cast<T>(x)
! Lies meine Posts bis zum Ende durch.const value_type a = static_cast<value_type> ( 1 ) / static_cast<value_type>( 2 );
Das ist nicht dieselbe Form wie in deinem Posting. In deinem Post war ein einziger Cast der gesamte Initializer. Hier ist der Initializer ein Ausdruck mit zwei Casts, den kann man natürlich nicht vereinfachen. Allerdings gibt es keinen Grund die Initialisierung in deinem Post zu
T value1(1);
vereinfachen.
Warum macht boost dann sowas?
Höchstwahrscheinlich nutzen die static_cast weil es entweder so in den Richtlinien steht, sie Casts im Code finden wollen (
static_cast
ist leicht zu suchen), etc. etc. Hier wird es genau dasselbe wievalue_type(1)
bewirken.
-
Arcoth schrieb:
Ja, aber
(T)x
ist doch für Klassen äquivalent zustatic_cast<T>(x)
! Lies meine Posts bis zum Ende durch.Schon klar, wie gesagt ich dachte es wäre anders
Arcoth schrieb:
Das ist nicht dieselbe Form wie in deinem Posting. In deinem Post war ein einziger Cast der gesamte Initializer. Hier ist der Initializer ein Ausdruck mit zwei Casts, den kann man natürlich nicht vereinfachen.
Hm Ok.
Arcoth schrieb:
Höchstwahrscheinlich nutzen die static_cast weil es entweder so in den Richtlinien steht, sie Casts im Code finden wollen (
static_cast
ist leicht zu suchen), etc. etc. Hier wird es genau dasselbe wievalue_type(1)
bewirken.Ok gut, alles klar. Wieder was gelernt
-
happystudent schrieb:
Schon klar, wie gesagt ich dachte es wäre anders
Ich verstehe jetzt erst was dein Satz bedeutet: Du wusstest nicht dass
T(x)
über(T)x
und schließlichstatic_cast
den Konstruktor aufruft, sondern direkt. Das habe ich zuerst missverstanden.
-
Arcoth schrieb:
Ich verstehe jetzt erst was dein Satz bedeutet: Du wusstest nicht dass
T(x)
über(T)x
und schließlichstatic_cast
den Konstruktor aufruft, sondern direkt. Das habe ich zuerst missverstanden.Kein Problem