C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Compilezeit Konstanten und Cast-Expressions

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ (German)
View previous topic :: View next topic  
Author Message
Marcel Müller
Guest





PostPosted: Sat Feb 18, 2006 8:06 pm    Post subject: Compilezeit Konstanten und Cast-Expressions Reply with quote



Hallo,

ich habe hier etwas mit (bösen) Defines herumgemacht um die
Standard-Funktionalität der Cast-Expressions partiell spezialisieren zu
können (für die einfachrere Verwendung von Smart-Pointern).

#define static_cast ::MM_static_cast

template <typename D, typename S>
inline D MM_static_cast(S s)
{ return MM_cast_traits<D,S>::do_static_cast(s);
}

Das klappt schon eine Weile lang sehr gut, nur scheppert es manchmal in
einem internen Include der Standardbibliothek. Da steht:

static const size_t table_size =
1 + static_cast<unsigned char>(-1);

Das Problem ist mir soweit klar. Da wird eine Compilezeit-Konstante
erwartet und eine Funktion kann (leider) niemals eine
Compilezeit-Konstante zurückliefern. *)


Nun zu den Fragen:

Ist der obige Ausdruck tatsächlich Standardkonform, oder klappt es nur
zufällig mit diesem Compiler (gcc 3.3.5)?
Anders gefragt, überlebt die Eigenschaft "Compilezeit-Konstante" eine
Cast-Expression? Wenn ja, wann?

Was könnte den Programmierer dazu bewogen haben, genau diesen, komischen
Ausdruck zu verwenden, um den Wertebereich eines char zu ermitteln?
Es gibt ja noch andere Methoden. Ist das besonders gut portabel?



*) Ich würde mir öfters wünschen, dass der Compiler bei
deterministischen Funktionen die compilierte Funktion direkt zur
Compilezeit aufrufen könnte und im Ergebnis wieder eine
Compilezeit-Konstante liefern würde. Bei bestimmten eingebauten
Funktionen geht es ja offenbar auch (z.B operator+<int>).
Das kann in speziellen Fällen (vor allem im Zusammenhang mit Templates)
eine beträchtliche Optimierung sein. Bei einem uralten C Compiler habe
ich sowas mal gesehen. Der hat z.B.
int i[strlen("asdf")];
akzeptiert. (Ein internes #pragma nosideeffects hat ihm die
erforderlichen Info über die geeigneten Funktionen gegeben.)


Marcel

--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
Back to top
Bob Hairgrove
Guest





PostPosted: Sat Feb 18, 2006 10:06 pm    Post subject: Re: Compilezeit Konstanten und Cast-Expressions Reply with quote



On Sat, 18 Feb 2006 20:32:39 +0100, Marcel Müller
<news.5.maazl (AT) spamgourmet (DOT) org> wrote:

Quote:
Hallo,

ich habe hier etwas mit (bösen) Defines herumgemacht um die
Standard-Funktionalität der Cast-Expressions partiell spezialisieren zu
können (für die einfachrere Verwendung von Smart-Pointern).

#define static_cast ::MM_static_cast

Soweit ich es weiss, ist ::MM_static_cast NICHT Teil der
Standard-C++-Sprache ... dagegen ist static_cast ein
C++-Schlüsselwort; allenfalls ist die Reihenfolge für #define hier
wohl vertauscht worden?!?! (falls der Compiler das auch schluckt,
müsste das unweigerlich zu undefiniertem Verhalten führen, IMHO...)

Quote:
template <typename D, typename S
inline D MM_static_cast(S s)
{ return MM_cast_traits<D,S>::do_static_cast(s);
}

Das klappt schon eine Weile lang sehr gut, nur scheppert es manchmal in
einem internen Include der Standardbibliothek. Da steht:

static const size_t table_size =
1 + static_cast<unsigned char>(-1);

Das Problem ist mir soweit klar. Da wird eine Compilezeit-Konstante
erwartet und eine Funktion kann (leider) niemals eine
Compilezeit-Konstante zurückliefern. *)


Nun zu den Fragen:

Ist der obige Ausdruck tatsächlich Standardkonform, oder klappt es nur
zufällig mit diesem Compiler (gcc 3.3.5)?
Anders gefragt, überlebt die Eigenschaft "Compilezeit-Konstante" eine
Cast-Expression? Wenn ja, wann?

Was könnte den Programmierer dazu bewogen haben, genau diesen, komischen
Ausdruck zu verwenden, um den Wertebereich eines char zu ermitteln?
Es gibt ja noch andere Methoden. Ist das besonders gut portabel?



*) Ich würde mir öfters wünschen, dass der Compiler bei
deterministischen Funktionen die compilierte Funktion direkt zur
Compilezeit aufrufen könnte und im Ergebnis wieder eine
Compilezeit-Konstante liefern würde. Bei bestimmten eingebauten
Funktionen geht es ja offenbar auch (z.B operator+<int>).
Das kann in speziellen Fällen (vor allem im Zusammenhang mit Templates)
eine beträchtliche Optimierung sein. Bei einem uralten C Compiler habe
ich sowas mal gesehen. Der hat z.B.
int i[strlen("asdf")];
akzeptiert. (Ein internes #pragma nosideeffects hat ihm die
erforderlichen Info über die geeigneten Funktionen gegeben.)


Marcel

--
Bob Hairgrove
NoSpamPlease (AT) Home (DOT) com

--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
Back to top
Stefan Reuther
Guest





PostPosted: Sat Feb 18, 2006 11:06 pm    Post subject: Re: Compilezeit Konstanten und Cast-Expressions Reply with quote



Marcel Müller wrote:
Quote:
#define static_cast ::MM_static_cast
[...]
Das klappt schon eine Weile lang sehr gut, nur scheppert es manchmal in
einem internen Include der Standardbibliothek. Da steht:

static const size_t table_size =
1 + static_cast<unsigned char>(-1);

Ein Programm darf keine reservierten Worte umdefinieren, wenn es die
Standardbibliothek nutzen will (17.4.3.1.1p2).

Quote:
Ist der obige Ausdruck tatsächlich Standardkonform, oder klappt es nur
zufällig mit diesem Compiler (gcc 3.3.5)?
Anders gefragt, überlebt die Eigenschaft "Compilezeit-Konstante" eine
Cast-Expression? Wenn ja, wann?

Immer.

Quote:
Was könnte den Programmierer dazu bewogen haben, genau diesen, komischen
Ausdruck zu verwenden, um den Wertebereich eines char zu ermitteln?
Es gibt ja noch andere Methoden. Ist das besonders gut portabel?

'static_cast<unsigned X>(-1)' bringt definitiv immer den größtmöglichen
Wert für den Typen 'unsigned X'. Von <climits> abgesehen sollte das die
portabelste Möglichkeit sein, den Wertebereich herauszufinden.

Quote:
*) Ich würde mir öfters wünschen, dass der Compiler bei
deterministischen Funktionen die compilierte Funktion direkt zur
Compilezeit aufrufen könnte und im Ergebnis wieder eine
Compilezeit-Konstante liefern würde.

Gerüchten zufolge soll der Wunsch in C++0x erhört werden.


Stefan

--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
Back to top
Marcel Müller
Guest





PostPosted: Sun Feb 19, 2006 3:06 pm    Post subject: Re: Compilezeit Konstanten und Cast-Expressions Reply with quote

Hallo,

Stefan Reuther wrote:
Quote:
Ein Programm darf keine reservierten Worte umdefinieren, wenn es die
Standardbibliothek nutzen will (17.4.3.1.1p2).

Das ist schon klar, aber zum Testen, wie kompatibel meine Implementation
ist, war es allemal gut. Den Punkt habe ich nie angezweifelt.


Quote:
Ist der obige Ausdruck tatsächlich Standardkonform, oder klappt es nur
zufällig mit diesem Compiler (gcc 3.3.5)?
Anders gefragt, überlebt die Eigenschaft "Compilezeit-Konstante" eine
Cast-Expression? Wenn ja, wann?

Immer.

Das überrascht mich jetzt ein wenig, denn eine Cast-Expression kann doch
auch einen Konstruktoraufruf und damit sogar andere Funktionsaufrufe
implizieren. Dann geht das doch gnadenlos in die Hose, oder?


Quote:
Was könnte den Programmierer dazu bewogen haben, genau diesen, komischen
Ausdruck zu verwenden, um den Wertebereich eines char zu ermitteln?
Es gibt ja noch andere Methoden. Ist das besonders gut portabel?

'static_cast<unsigned X>(-1)' bringt definitiv immer den größtmöglichen
Wert für den Typen 'unsigned X'. Von <climits> abgesehen sollte das die
portabelste Möglichkeit sein, den Wertebereich herauszufinden.

Und was macht man bei vorzeichenbehafteten Typen?

Irgendeine Implikation ist immer drin. In diesem Fall eben, dass die
binäre Darstellung der negativen Zahlen wirklich auf genau diesem Wege
erfolgt. Es gab (gibt?) ja auch Architekturen, die mit Offset gearbeitet
haben. Wie sich der Cast-Operator im Bezug auf nichtdefinierte
Wertemappings verhält, sei mal dahingestellt. Da würde ich climits als
die portablere Methode bezeichnen.


Quote:
*) Ich würde mir öfters wünschen, dass der Compiler bei
deterministischen Funktionen die compilierte Funktion direkt zur
Compilezeit aufrufen könnte und im Ergebnis wieder eine
Compilezeit-Konstante liefern würde.

Gerüchten zufolge soll der Wunsch in C++0x erhört werden.

Schau an, das wäre nett.


Marcel

--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
Back to top
Stefan Reuther
Guest





PostPosted: Sun Feb 19, 2006 6:06 pm    Post subject: Re: Compilezeit Konstanten und Cast-Expressions Reply with quote

Marcel Müller wrote:
Quote:
Stefan Reuther wrote:
Ist der obige Ausdruck tatsächlich Standardkonform, oder klappt es nur
zufällig mit diesem Compiler (gcc 3.3.5)?
Anders gefragt, überlebt die Eigenschaft "Compilezeit-Konstante" eine
Cast-Expression? Wenn ja, wann?

Immer.

Das überrascht mich jetzt ein wenig, denn eine Cast-Expression kann doch
auch einen Konstruktoraufruf und damit sogar andere Funktionsaufrufe
implizieren. Dann geht das doch gnadenlos in die Hose, oder?

Ein konstanter Ausdruck darf nur eingebaute oder enum-Typen haben. Und
die haben keine Konstruktoren.

Wobei der Standard hier etwas fischig geschrieben ist. Vom Wortlaut her ist
(int) 0.5
ein gültiger konstanter integraler Ausdruck (und damit eine gültige
Nullzeiger-Konstante),
(int) (double) 0.5
aber nicht (weil ein integral constant-expression keine Typumwandlungen
zu float-Typen enthalten darf).

Quote:
Was könnte den Programmierer dazu bewogen haben, genau diesen, komischen
Ausdruck zu verwenden, um den Wertebereich eines char zu ermitteln?
Es gibt ja noch andere Methoden. Ist das besonders gut portabel?

'static_cast<unsigned X>(-1)' bringt definitiv immer den größtmöglichen
Wert für den Typen 'unsigned X'. Von <climits> abgesehen sollte das die
portabelste Möglichkeit sein, den Wertebereich herauszufinden.

Und was macht man bei vorzeichenbehafteten Typen?

Das ist ne andere Baustelle. Dass es mit vorzeichenbehafteten Typen
nicht geht, hindert einen nicht daran, es mit vorzeichenlosen Typen
dennoch zu tun.

Quote:
Irgendeine Implikation ist immer drin. In diesem Fall eben, dass die
binäre Darstellung der negativen Zahlen wirklich auf genau diesem Wege
erfolgt. Es gab (gibt?) ja auch Architekturen, die mit Offset gearbeitet
haben.

"Offset" ist m.M.n. nicht zulässig. Das Bitmuster für eine 0 in einem
vorzeichenlosen Typ muss "alle Bits 0 sein", und die Bitmuster für
Werte, die sowohl in 'signed X', als auch in 'unsigned X' darstellbar
sind (also z.B. 0) müssen identisch sein (3.9.1p3). Ergo ist eine
Darstellung von vorzeichenbehafteten Zahlen als "Wert + Offset" nicht
zulässig.

Die zulässigen und sinnvollen Varianten sind Einerkomplement, Zweier-
komplement und Vorzeichen-Wert-Darstellung. Allen dreien gemein ist,
dass INT_MAX = static_cast<int>(static_cast<unsigned int>(-1) >> 1) ist.

Theoretisch möglich sind noch Implementationen, wo z.B. 0x7FFF eine
trap-representation ist. Aber mir ist ehrlich gesagt nicht mal eine
bekannt, die nicht Zweierkomplement verwendet.

Quote:
Wie sich der Cast-Operator im Bezug auf nichtdefinierte
Wertemappings verhält, sei mal dahingestellt. Da würde ich climits als
die portablere Methode bezeichnen.

Ja. Der Vorteil von static_cast<unsigned X>(-1) ist aber eben, dass es
nur mit Elementen der Sprache auskommt, ohne Bibliothek.

Okay, es gibt noch eine andere, die (unter der Voraussetzung, dass es
keine trap-representations gibt) nur mit Sprachelementen auskommt.
template<typename T, T val, bool iterate>
struct checker {
enum { value = T(val-1) };
};
template<typename T, T val>
struct checker<T, val, true> {
enum { value = checker<T, T(val+1), (T(val+1) > T(val))>::value };
};
template<typename T>
struct get_max {
enum { value = checker<T, 0, true>::value };
};
int main() {
std::cout << get_max<char>::value << "\n";
}
Aber erzähl bitte niemandem, dass ich das geschrieben hab :-)


Stefan

--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
Back to top
kanze
Guest





PostPosted: Mon Feb 20, 2006 2:06 pm    Post subject: Re: Compilezeit Konstanten und Cast-Expressions Reply with quote

Marcel Müller wrote:

Quote:
ich habe hier etwas mit (bösen) Defines herumgemacht um die
Standard-Funktionalität der Cast-Expressions partiell
spezialisieren zu können (für die einfachrere Verwendung von
Smart-Pointern).

#define static_cast ::MM_static_cast

template <typename D, typename S
inline D MM_static_cast(S s)
{ return MM_cast_traits<D,S>::do_static_cast(s);
}

Das klappt schon eine Weile lang sehr gut, nur scheppert es
manchmal in einem internen Include der Standardbibliothek.

Dagegen, §17.4.3.1.1/2: "A translation unit that includes a
header shall not contain any macros that define names declared
or defined in that header. Nor shall such a translation unit
define macros for names lexically identical to keywords." Also,
du darfst es nur machen, wenn du keine standard-Kopfdateien
includierst.

Quote:
Da steht:

static const size_t table_size =
1 + static_cast<unsigned char>(-1);

Das Problem ist mir soweit klar. Da wird eine
Compilezeit-Konstante erwartet und eine Funktion kann (leider)
niemals eine Compilezeit-Konstante zurückliefern. *)

Nun zu den Fragen:

Ist der obige Ausdruck tatsächlich Standardkonform, oder
klappt es nur zufällig mit diesem Compiler (gcc 3.3.5)?

Es ist vollig Standardkonform, und kommt sogar häufig in
maschinnahen Ebenen vor.

Quote:
Anders gefragt, überlebt die Eigenschaft
"Compilezeit-Konstante" eine Cast-Expression? Wenn ja, wann?

Ein konstanter Ausdruck darf Umwandlungen enthalten, siehe
§5.19.

Quote:
Was könnte den Programmierer dazu bewogen haben, genau diesen,
komischen Ausdruck zu verwenden, um den Wertebereich eines
char zu ermitteln? Es gibt ja noch andere Methoden.

Zum Beispiel?

Quote:
Ist das besonders gut portabel?

Es ist die gewöhnliche Methode. Es muss mit jedem konformen
Compiler funktionnieren.

Quote:
*) Ich würde mir öfters wünschen, dass der Compiler bei
deterministischen Funktionen die compilierte Funktion direkt
zur Compilezeit aufrufen könnte und im Ergebnis wieder eine
Compilezeit-Konstante liefern würde.

Es wird darüber gesprochen, habe ich gehört.

Quote:
Bei bestimmten eingebauten Funktionen geht es ja offenbar auch
(z.B operator+<int>).

Das ist keine "eingebaute Funktion". Es wird nur als solche zum
Zweck des Auflösens von überladenen Funktionen betrachtet. Am
sonsten ist + ein Operator, deren Semantik in §5.7 beschrieben
wird.

Quote:
Das kann in speziellen Fällen (vor allem im Zusammenhang mit
Templates) eine beträchtliche Optimierung sein. Bei einem
uralten C Compiler habe ich sowas mal gesehen. Der hat z.B.
int i[strlen("asdf")];
akzeptiert. (Ein internes #pragma nosideeffects hat ihm die
erforderlichen Info über die geeigneten Funktionen gegeben.)

Das ist heutzutag in C erlaubt. Nicht aber in C++. (In C++
schreibt man ehe "std::vector< int > i( strlen("asdf") );".)

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
Back to top
kanze
Guest





PostPosted: Mon Feb 20, 2006 3:06 pm    Post subject: Re: Compilezeit Konstanten und Cast-Expressions Reply with quote

Marcel Müller wrote:
Quote:
Stefan Reuther wrote:

Ein Programm darf keine reservierten Worte umdefinieren,
wenn es die Standardbibliothek nutzen will (17.4.3.1.1p2).

Das ist schon klar, aber zum Testen, wie kompatibel meine
Implementation ist, war es allemal gut. Den Punkt habe ich nie
angezweifelt.

Ist der obige Ausdruck tatsächlich Standardkonform, oder
klappt es nur zufällig mit diesem Compiler (gcc 3.3.5)?
Anders gefragt, überlebt die Eigenschaft
"Compilezeit-Konstante" eine Cast-Expression? Wenn ja, wann?

Immer.

Das überrascht mich jetzt ein wenig, denn eine Cast-Expression
kann doch auch einen Konstruktoraufruf und damit sogar andere
Funktionsaufrufe implizieren. Dann geht das doch gnadenlos in
die Hose, oder?

Benutzerdefinierten Typen dürfen nie in einem konstanten
Ausdruck vorkomment.

Quote:
Was könnte den Programmierer dazu bewogen haben, genau
diesen, komischen Ausdruck zu verwenden, um den Wertebereich
eines char zu ermitteln? Es gibt ja noch andere Methoden.
Ist das besonders gut portabel?

'static_cast<unsigned X>(-1)' bringt definitiv immer den
größtmöglichen Wert für den Typen 'unsigned X'. Von
climits> abgesehen sollte das die portabelste Möglichkeit
sein, den Wertebereich herauszufinden.

Und was macht man bei vorzeichenbehafteten Typen?

static_cast< unsigned X >( -1 ) >> 1 (für den ganzzahligen Typ
X).

Quote:
Irgendeine Implikation ist immer drin.

Freilich. Hauptsächlich, die Implikation, dass der Compiler
schau ist.

Quote:
In diesem Fall eben, dass die binäre Darstellung der negativen
Zahlen wirklich auf genau diesem Wege erfolgt.

Darstellung hat nichts darin zu suchen. Die Norm sagt, dass
static_cast< unsigned X >( -1 ) das größte Wert von unsigned X
zurückliefert. Alles anderes ist Problem des Compilers.

In der Tat sagt die Norm, dass ganzzahlige Type ohne Vorzeichen
rein binärisch dargestellt werden müssen. Und auch, dass
unsigned Typen immer Modulo 2^n arbeiten, wo n der Anzahl
bedeutender Bits ist.

Quote:
Es gab (gibt?) ja auch Architekturen, die mit Offset
gearbeitet haben.

Meinst du, wo 0 nicht mit allen Bits gleich 0 dargestellt wird.
In C/C++ ist das verboten. Bei den unsigned Typen muss rein
binär gearbeitet werden; höchst kann es Pad-Bits geben, die aber
dem Programmierer nicht direkt sichtbar sind, weil sie in der
Darstellung des Wertes keine Role spielen.

Bei signed wird es verlangt, dass die Darstellung Werte, die
auch im entsprechenden unsigned passen, dieselbe sein, als im
unsigned. (Was indirekt bedeutet, dass das Vorzeichen das
höchstwertigste Bit sein muss.)

Quote:
Wie sich der Cast-Operator im Bezug auf nichtdefinierte
Wertemappings verhält, sei mal dahingestellt.

Die Norm legt einiges Fest. Besonders bei unsigned Typen.

Quote:
Da würde ich climits als die portablere Methode bezeichnen.

Freilich. Portabler, nicht, aber die Bedeutung von UINT_MAX ist
wohl klarer als static_cast< unsigned int >( -1 ), denke ich,
auch wenn beide den gleichen Wert ergeben.

Quote:
*) Ich würde mir öfters wünschen, dass der Compiler bei
deterministischen Funktionen die compilierte Funktion direkt
zur Compilezeit aufrufen könnte und im Ergebnis wieder eine
Compilezeit-Konstante liefern würde.

Gerüchten zufolge soll der Wunsch in C++0x erhört werden.

Schau an, das wäre nett.

§6.7.5.2 von C-99. Wird *wahrscheinlicherweise* in den nächsten
C++-Version übernommen. Mehr kann man eigentlich nicht sagen;
der genaue Inhalt von c++0x, wie den Wert von x, steht noch
nicht fest. (Es ist nicht ohne Nachteile. Z.B. sizeof ist nicht
mehr unbedingt eine Konstante. Wenn es in einer Klasse vorkommt,
geht es auch nicht ohne Probleme betriffs Derivation.)

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ (German) All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.