[C++] long long -> int: possible dataloss warning voorkomen

Pagina: 1
Acties:

Acties:
  • 0 Henk 'm!

  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
Een functie die een database veld returned als integer returned een long long. Echter, niet alle variabelen zijn long long, dat is niet nodig. Dit levert echter wel overal dataloss warnings op. Die warning zet ik nu gewoon uit, maar is er geen betere manier?
Overal een static_cast toevoegen, daar heb ik ook geen zin in.

Acties:
  • 0 Henk 'm!

  • Defspace
  • Registratie: Mei 2000
  • Laatst online: 29-04 22:59

Defspace

Administrator

Kan je die functie niet gewoon een integer laten returnen?

Acties:
  • 0 Henk 'm!

  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
Soms is long long natuurlijk wel nodig.

Acties:
  • 0 Henk 'm!

  • CoolGamer
  • Registratie: Mei 2005
  • Laatst online: 06-09 16:59

CoolGamer

What is it? Dragons?

De enige manier is zover ik weet een cast of de warning uitzetten.

Waarom maak je het in eerste instantie een long long als het in veel gevallen gebruikt wordt als een int?

¸.·´¯`·.¸.·´¯`·.¸><(((º>¸.·´¯`·.¸><(((º>¸.·´¯`·.¸.·´¯`·.¸.·´¯`·.¸<º)))><¸.·´¯`·.¸.·´¯`·.¸.·´¯`·.¸


Acties:
  • 0 Henk 'm!

  • Snake
  • Registratie: Juli 2005
  • Laatst online: 07-03-2024

Snake

Los Angeles, CA, USA

Defspace schreef op zaterdag 25 juli 2009 @ 20:38:
Kan je die functie niet gewoon een integer laten returnen?
Neen want TS zegt dat hij soms wel een long long nodig heeft.

@TS: Ik denk toch dat dit handmatig moet gaan hoor.

Going for adventure, lots of sun and a convertible! | GMT-8


Acties:
  • 0 Henk 'm!

  • Reptile209
  • Registratie: Juni 2001
  • Laatst online: 22:59

Reptile209

- gers -

Waarom zet je de functieoutput niet gewoon in een long long variabele? Dan kan je 'm in verder gebruik altijd nog casten naar een int als dat nodig is. Of is het allemaal zo geheugencritisch dat dat geen optie is?

Zo scherp als een voetbal!


Acties:
  • 0 Henk 'm!

  • user109731
  • Registratie: Maart 2004
  • Niet online
Kun je niet een (wrapper) functie toevoegen die int teruggeeft? Dan hoef je iig niet overal te casten...

Acties:
  • 0 Henk 'm!

  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
Dat is inderdaad een optie ja. Vergelijkbaar met de cast, maar simpelere syntax.
Reptile209 schreef op zaterdag 25 juli 2009 @ 20:45:
Waarom zet je de functieoutput niet gewoon in een long long variabele? Dan kan je 'm in verder gebruik altijd nog casten naar een int als dat nodig is. Of is het allemaal zo geheugencritisch dat dat geen optie is?
Dat is geen fatsoenlijke optie. Dan krijg je een cascade effect en wordt er veel te veel long long.

Acties:
  • 0 Henk 'm!

  • bobo1on1
  • Registratie: Juli 2001
  • Laatst online: 18-05 17:57
Een andere optie is een template gebruiken, maar dan moet je weer overal <int> of <long long> neerzetten.

Persoonlijk zou ik de warning uitzetten, het is een geldige impliciete cast waar je zelf de gevolgen wel van overziet.

[ Voor 36% gewijzigd door bobo1on1 op 26-07-2009 00:39 ]

Impedance, a measure of opposition to time-varying electric current in an electric circuit.
Not to be confused with impotence.


Acties:
  • 0 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 22:22
In zulke gevallen zou ik zelf wel expliciet naar int casten en de warning aan laten staan (om onbedoelde conversies toch af te vangen) maar ik gebruik dan wel C-style casts omdat ik geen zin heb om static_cast<int>() te typen als (int) ook volstaat.

Alternatief is een aparte functie maken die een waarde als integer ophaalt, en die aanroepen waar je een integer verwacht. Het is zonder code een beetje lastig inschatten of dat een redelijk alternatief is in jouw situatie.

Wat betreft "...is er een betere manier" zul je, denk ik, weinig bevredigende antwoorden krijgen, want er zijn meerdere acceptabele manieren om dit te doen (zoals je zelf ook al bedacht had) dus uiteindelijk komt het er maar net op aan welke aanpak jouw voorkeur heeft. (Maar goed, misschien doet iemand een suggestie die je aanspreekt maar nog niet zelf bedacht had.)

[ Voor 52% gewijzigd door Soultaker op 26-07-2009 02:54 ]


Acties:
  • 0 Henk 'm!

Verwijderd

is een long long niet gewoon een 8-byte int? dan is het niet zo vreemd dat hij begint te mekkeren als je hem als int (usually 4-byte) gebruikt. Of zit ik weer eens onzin uit te kramen? Ja dus... |:(

[ Voor 5% gewijzigd door Verwijderd op 26-07-2009 03:44 ]


Acties:
  • 0 Henk 'm!

Verwijderd

bobo1on1 schreef op zondag 26 juli 2009 @ 00:20:
Een andere optie is een template gebruiken, maar dan moet je weer overal <int> of <long long> neerzetten.
Dit lijkt me de enige correcte optie.
Persoonlijk zou ik de warning uitzetten, het is een geldige impliciete cast waar je zelf de gevolgen wel van overziet.
Als je de juiste typen altijd gebruikt hoéf je niet meer na te denken of er gevolgen zouden kunnen zijn. Maakt het onderhouden / debuggen ook makkelijker, dunkt me.

Acties:
  • 0 Henk 'm!

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Olaf van der Spek schreef op zaterdag 25 juli 2009 @ 20:36:
Echter, niet alle variabelen zijn long long, dat is niet nodig.
Olaf van der Spek schreef op zaterdag 25 juli 2009 @ 20:40:
Soms is long long natuurlijk wel nodig.
Mis ik iets? :) Heb je nou wel of geen long long nodig? Dit vraagt echt om hele vervelende bugs over 3 jaar...

Acties:
  • 0 Henk 'm!

  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
Zoijar schreef op zondag 26 juli 2009 @ 12:29:
Mis ik iets? :) Heb je nou wel of geen long long nodig? Dit vraagt echt om hele vervelende bugs over 3 jaar...
Soms wel en soms niet. Niet al mijn database velden zijn bigint (MySQL), sommige wel. Ik gebruik echter wel voor alle integer velden dezelfde functie.

Het nadeel van een cast of aparte functie is dat als ik het type van een variabele verander, ook al die casts weer moet aanpassen. Die casts zijn in feite code duplicatie, wat niet goed is.

Is er geen optie die warning alleen uit te schakelen voor het return value van deze functie?

Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 17-09 14:05

.oisyn

Moderator Devschuur®

Demotivational Speaker

Olaf van der Spek schreef op zondag 26 juli 2009 @ 18:37:
Het nadeel van een cast of aparte functie is dat als ik het type van een variabele verander, ook al die casts weer moet aanpassen.
Daar heb je typedefs voor. Vergeet trouwens niet dat je ook gewoon een ctor cast kunt gebruiken, dus int(foo()) ipv (int)foo(). Heb je hetzelfde effect als een aparte functie, maar dan zonder aparte functie :)
Is er geen optie die warning alleen uit te schakelen voor het return value van deze functie?
Misschien handig om erbij te zeggen welke compiler je gebruikt? ISO C++ zegt overigens niets over dergelijke warnings, een long long opslaan in een int zonder cast is gewoon well-formed.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
Een aparte typedef voor elke variabele?
Misschien handig om erbij te zeggen welke compiler je gebruikt? ISO C++ zegt overigens niets over dergelijke warnings, een long long opslaan in een int zonder cast is gewoon well-formed.
VC9.

Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 17-09 14:05

.oisyn

Moderator Devschuur®

Demotivational Speaker

Olaf van der Spek schreef op zondag 26 juli 2009 @ 20:55:
[...]

Een aparte typedef voor elke variabele?
Natuurlijk niet, maar je gaat toch ook niet per variabele besluiten of je het type gaat veranderen? Je categoriseert ze op basis van semantiek. Vergelijkbaar met de standaard defines als size_t voor het opslaan van groottes en aantallen en ptrdiff_t voor het opslaan van pointerverschillen.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • farlane
  • Registratie: Maart 2000
  • Laatst online: 16-09 22:43
.oisyn schreef op zondag 26 juli 2009 @ 18:53:
Misschien handig om erbij te zeggen welke compiler je gebruikt? ISO C++ zegt overigens niets over dergelijke warnings, een long long opslaan in een int zonder cast is gewoon well-formed.
Komt dat niet simpelweg omdat C++ niet definieert dat een int kleiner moet zijn dan een long long? Een dergelijke warning is volgens mij wel degelijk op zijn plaats hier nl.

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 17-09 14:05

.oisyn

Moderator Devschuur®

Demotivational Speaker

Nee, dat komt omdat C++ definieert dat alle built-in valuetypes gewoon impliciet naar elkaar geconverteerd kunnen worden. Dus ook een long double naar een char. Dat een implementatie een warning geeft is de keuze van die implementatie :) (en dat ie op z'n plaats is kan ik het alleen maar mee eens zijn - van mij had het ook wel een error mogen zijn, zoals in Java en C# het geval is)

[ Voor 42% gewijzigd door .oisyn op 26-07-2009 22:55 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • MLM
  • Registratie: Juli 2004
  • Laatst online: 12-03-2023

MLM

aka Zolo

waarom doen we allemaal zo ingewikkeld, het is een warning, niet een error :)
als de topicstarter de warning wil negeren, dan kan ie dat gewoon doen (door of gewoon warnings niet te lezen, of door in de compiler opties specifiek die warning uit te zetten).

zolang als je niet van plan bent om je code op een andere compiler te compilen, kan je eventueel los gaan met een "#pragma warning(disable, <je warningcode hier>)" bovenaan de sourcefile waarin je de warnings wilt negeren. op die manier kan je per sourcefile warnings uitzetten, wat op zich wel fijner is (je kan natuurlijk ook per source file de compiler opties aanpassen, maar in mijn ervaring word dat meestal een untracable rotzooi na een tijdje)

-niks-


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 17-09 14:05

.oisyn

Moderator Devschuur®

Demotivational Speaker

MLM schreef op maandag 27 juli 2009 @ 20:53:
waarom doen we allemaal zo ingewikkeld, het is een warning, niet een error :)
En de TS vroeg zich af of hij dat niet voor specifieke situaties uit kan zetten. Wie doet hier moeilijk? :) Overigens compileren wij zelf met warnings als errors, dus dan moet je er wel wat aan doen.
zolang als je niet van plan bent om je code op een andere compiler te compilen, kan je eventueel los gaan met een "#pragma warning(disable, <je warningcode hier>)" bovenaan de sourcefile waarin je de warnings wilt negeren.
Kan ook als je met een andere compiler aan de slag wil. #pragma is daar per definitie voor geschikt, omdat compilers dat gewoon mogen negeren.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • farlane
  • Registratie: Maart 2000
  • Laatst online: 16-09 22:43
MLM schreef op maandag 27 juli 2009 @ 20:53:
waarom doen we allemaal zo ingewikkeld, het is een warning, niet een error :)
Warnings zijn vies. Ze worden bovendien niet voor niets gegeven, en verdienen aandacht. ( Met de mogelijkheid om na er over nagedacht te hebben een cast te doen of een warning tijdelijk te disablen )

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


Acties:
  • 0 Henk 'm!

  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
farlane schreef op dinsdag 28 juli 2009 @ 00:09:
Warnings zijn vies. Ze worden bovendien niet voor niets gegeven, en verdienen aandacht. ( Met de mogelijkheid om na er over nagedacht te hebben een cast te doen of een warning tijdelijk te disablen )
Casts om warnings te voorkomen vind ik eigenlijk vies. Tenzij je een typedef gebruikt is het code/type duplication. Zelfs met een typedef is het duplicatie, hopelijkt klopt de typedef nog.

[ Voor 7% gewijzigd door Olaf van der Spek op 28-07-2009 12:45 ]


Acties:
  • 0 Henk 'm!

  • Hydra
  • Registratie: September 2000
  • Laatst online: 21-08 17:09
Wat is er mis met een expliciete cast?

https://niels.nu


Acties:
  • 0 Henk 'm!

  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
Type duplication

Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 17-09 14:05

.oisyn

Moderator Devschuur®

Demotivational Speaker

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
template<class T> class olaf_cast_t
{
    olaf_cast_t(T t) : value(t) { }
    template<class U> operator U() const { return static_cast<U>(value); }
    T value;
};

template<class T> olaf_cast_t<T> olaf_cast(T t)
{
    return olaf_cast_t<T>(t);
}

long long foo();
float bar();

int main()
{
    char c = olaf_cast(foo());
    short s = olaf_cast(bar());
}

Weg type duplication ;)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

.oisyn schreef op dinsdag 28 juli 2009 @ 15:08:
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
template<class T> class olaf_cast_t
{
    olaf_cast_t(T t) : value(t) { }
    template<class U> operator U() const { return static_cast<U>(value); }
    T value;
};

template<class T> olaf_cast_t<T> olaf_cast(T t)
{
    return olaf_cast_t<T>(t);
}

long long foo();
int bar();

int main()
{
    char c = olaf_cast(foo());
    short s = olaf_cast(bar());
}

Weg type duplication ;)
Sweet, maar wel een beetje eng ;) Volgens mij heb ik hier wel eens weken naar gezocht; is dit niet een oplossing voor assignment van template return types in bijvoorbeeld expression templates? Ik roep maar wat, geen idee meer, maar het komt me zo bekend voor dit.

[ Voor 16% gewijzigd door Zoijar op 28-07-2009 15:16 ]


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 17-09 14:05

.oisyn

Moderator Devschuur®

Demotivational Speaker

Zoijar schreef op dinsdag 28 juli 2009 @ 15:11:
is dit niet een oplossing voor assignment van template return types in bijvoorbeeld expression templates?
Geen idee? Zou best kunnen, al zie ik niet direct hoe. Je kunt met C++03 nu eenmaal niet weten wat het type van a+b is om dat te returnen uit een functie, wat de hele reden is dat C++0x decltype introduceert.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
Het kon niet lang duren voordat zoiets gepost zou worden natuurlijk. :p

[ Voor 3% gewijzigd door Olaf van der Spek op 28-07-2009 19:20 ]


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 17-09 14:05

.oisyn

Moderator Devschuur®

Demotivational Speaker

We doen er een beetje grappig over maar eigenlijk is dit precies wat je wilt. Goed, je zal het waarschijnlijk geen 'olaf_cast' noemen :P, maar het is toch een expliciete cast zonder dat je hoeft te weten wat voor type je naartoe cast. Je kunt dus gewoon types wijzigen in je applicatie zonder dat je overal de casts moet gaan aanpassen. En tegelijkertijd blijft het duidelijk dat je wel aan het casten bent. En wat performance betreft zal het denk ik resulteren in identieke instructies. En met iets meer template magic zou je het eventueel nog kunnen limiteren aan bepaalde types, zodat je niet per ongeluk een base* naar een derived* cast.

[ Voor 20% gewijzigd door .oisyn op 28-07-2009 20:54 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • Punkie
  • Registratie: Oktober 2005
  • Laatst online: 15-08 20:48
C++:
1
2
3
4
5
long long getDBresult();
typedef int type1;

type1 result = (type1)getDBresult();
long long longresult = getDBresult();

Je hoeft bij een type wijziging maar op 1 plaats te kijken (de typedef). Geen duplicatie.
Als de variabele van type verandert dan verander je de semantiek en moet je een ander programma schrijven. Wie onder die verplichting probeert uit te komen moet vieze hacks toepassen die de geneugten van het C type checking (deels, gecontroleert) te niet doen. En zou daarbij een vette compiler warning moeten verdienen :P


a = int(var); vs a = (int)var;
Wanneer is een constructor cast verschillend van een opertor cast? De operator cast zou (in dit geval) geen extra instructies toevoegen. Een constructor zou een nieuwe variabele aanmaken maar in dit voorbeeld wordt het aanmaken van de nieuwe variable gewoon hetzelfde als de assignement van die variabele aan a.
Dus er is toch geen verschil, wel?

[ Voor 0% gewijzigd door Punkie op 29-07-2009 11:12 . Reden: typo ]


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 17-09 14:05

.oisyn

Moderator Devschuur®

Demotivational Speaker

Typedefs waren al voorgesteld :)
Wel duplicatie. Je moet type1 typen, ookal weet je dat de variabele waar je aan assignt ook van datzelfde type is.
Wie onder die verplichting probeert uit te komen moet vieze hacks toepassen die de geneugten van het C type checking (deels, gecontroleert) te niet doen.
Zoals ik eerder al zei, C++ verbiedt je helemaal niet om (zonder warning) een long double aan impliciet naar een char te converten. Het warninglevel van deze specifieke VC++ warning is level 4 (vrij hoog dus). Compilers als GCC En Comeau geven by default niet eens een warning. Dus, over welke type checking had je het ook alweer? :)
a = int(var); vs a = (int)var;
Wanneer is een constructor cast verschillend van een opertor cast?
Nooit. 5.2.3/1.
5.2.3 Explicit type conversion (functional notation)
1 A simple-type-specifier (7.1.5) followed by a parenthesized expression-list constructs a value of the specified type given the expression list. 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).

[ Voor 55% gewijzigd door .oisyn op 29-07-2009 11:31 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • Punkie
  • Registratie: Oktober 2005
  • Laatst online: 15-08 20:48
.oisyn schreef op woensdag 29 juli 2009 @ 11:10:
Wel duplicatie. Je moet type1 typen, ook al weet je dat de variabele waar je aan assignt ook van datzelfde type is.
Ok, het verschil tussen de (type1) cast en de template oplossing is dat er andere letters op het klavier moeten worden aangeslagen. Beide oplossingen vereisen dat er voor elke cast-warning-onderdrukking iets moet worden geplaatst. Evenveel moeite.
type1 result = <iets>(getDBresult();

Technisch gezien dupliceer je dus een string die dezelfde is als de identifier voor dit type. Dit is niet hetzelfde als type duplication omdat je de definitie van het type niet dupliceert. imho
Zelfs indien dit niet zo is dan zijn beide oplossing evenwaardig hier en is het "type duplication" argument niet van toepassing.

Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 17-09 14:05

.oisyn

Moderator Devschuur®

Demotivational Speaker

Punkie schreef op woensdag 29 juli 2009 @ 11:33:
[...]


Ok, het verschil tussen de (type1) cast en de template oplossing is dat er andere letters op het klavier moeten worden aangeslagen.
Nee, het verschil met de template oplossing is dat de template oplossing nooit wijzigt, ookal verander je het type van de variabele. De typedef suggestie is geen volledige oplossing, omdat je niet per variabele een typedef gaat maken (dat is ononderhoudbaar), en dus ga je typen categoriseren. Als je later besluit dat een variabele naar een andere categorie moet (waardoor het type alias dus verandert, ook al blijft het daadwerkelijke type hetzelfde), dan zul je alsnog de casts moeten aanpassen.
Dit is niet hetzelfde als type duplication omdat je de definitie van het type niet dupliceert. imho
You're arguing semantics. Ook al heb je gelijk, de topicstarter wil gewoon niet nog een keer dat type willen typen. Dan kun je wel zeggen dat dat geen type duplication heet, maar eigenlijk doet dat er niet zo heel veel toe :)

[ Voor 23% gewijzigd door .oisyn op 29-07-2009 11:43 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • Punkie
  • Registratie: Oktober 2005
  • Laatst online: 15-08 20:48
.oisyn schreef op woensdag 29 juli 2009 @ 11:10:

Zoals ik eerder al zei, C++ verbiedt je helemaal niet om (zonder warning) een long double aan impliciet naar een char te converten.
Correct, niet de C type checking maar de compiler's compile time checking dus. Wat in dit geval ontegensprekelijk zeer nuttig is... En in andere gevallen ook..
Dus wie er onder uit wil komen moet wat hacken...

Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 17-09 14:05

.oisyn

Moderator Devschuur®

Demotivational Speaker

Punkie schreef op woensdag 29 juli 2009 @ 11:45:
Dus wie er onder uit wil komen moet wat hacken...
Ik geloof dat dat al was vastgesteld ja ;)
En als we het toch over semantiek hebben, C is geen C++. En zeker als je het hebt over typechecking dan is C daar veel coulanter in dan C++

[ Voor 27% gewijzigd door .oisyn op 29-07-2009 11:55 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • Punkie
  • Registratie: Oktober 2005
  • Laatst online: 15-08 20:48
.oisyn schreef op woensdag 29 juli 2009 @ 11:40:
Nee, het verschil met de template oplossing is dat de template oplossing nooit wijzigt, ookal verander je het type van de variabele.
Wel als je veronderstelt dat je de semantiek van de variabele niet verandert. (en dus niet aan "type2 result" gaat wijzigen).
Deze veronderstelling denk ik te mogen maken omdat we hier spreken over een oplossing voor dit specifiek geval. Ik verwacht niet om met dit probleem vaak geconfronteerd te worden (indien wel, dan ik de template oplossing gemakkelijker).
.oisyn schreef op woensdag 29 juli 2009 @ 11:40:
De typedef suggestie is geen volledige oplossing, omdat je niet per variabele een typedef gaat maken (dat is ononderhoudbaar), en dus ga je typen categoriseren.
Dit is een no-brainer. Natuurlijk categoriseren we types. Bijgevolg moet ik de lettertje van de cast operatie niet aanpassen.

Acties:
  • 0 Henk 'm!

  • Punkie
  • Registratie: Oktober 2005
  • Laatst online: 15-08 20:48
.oisyn schreef op woensdag 29 juli 2009 @ 11:54:
Ik geloof dat dat al was vastgesteld ja ;)
Met deze dus dank aan mezelf voor het samenvatten voor Olaf.
Gemakkelijker dan een cast kan je het dus niet krijgen. Met wat gehack verlicht je misschien wat het schrijfwerk maar verlies je de warnings.
<rant>Het aanpassen van de C++ DB access functies of het aanpassen van de DB layout zou misschien wel eens netter kunnen zijn. Minder kans op fouten, een DB model dat beter aansluit op je mentale model, ....nagnagnag. Kortom misschien is je conversion-warning-onderdrukking wel niet een goed idee</rant>

Acties:
  • 0 Henk 'm!

  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
.oisyn schreef op woensdag 29 juli 2009 @ 11:10:
Zoals ik eerder al zei, C++ verbiedt je helemaal niet om (zonder warning) een long double aan impliciet naar een char te converten. Het warninglevel van deze specifieke VC++ warning is level 4 (vrij hoog dus).
double -> char is W2 (in VC9)
int -> smaller is W4
iets anders -> smaller is W3
Punkie schreef op woensdag 29 juli 2009 @ 12:01:
Dit is een no-brainer. Natuurlijk categoriseren we types. Bijgevolg moet ik de lettertje van de cast operatie niet aanpassen.
Totdat je de categorie van een variabele veranderd.
Punkie schreef op woensdag 29 juli 2009 @ 12:01:
Wel als je veronderstelt dat je de semantiek van de variabele niet verandert. (en dus niet aan "type2 result" gaat wijzigen).
Wel? Nee, er veranderd niks behalve het type van de variabele.
Punkie schreef op woensdag 29 juli 2009 @ 12:11:
Gemakkelijker dan een cast kan je het dus niet krijgen. Met wat gehack verlicht je misschien wat het schrijfwerk maar verlies je de warnings.
Met de cast ben ik de warnings toch ook kwijt?
<rant>Het aanpassen van de C++ DB access functies of het aanpassen van de DB layout zou misschien wel eens netter kunnen zijn. Minder kans op fouten, een DB model dat beter aansluit op je mentale model, ....nagnagnag. Kortom misschien is je conversion-warning-onderdrukking wel niet een goed idee</rant>
Wat zou je willen aanpassen aan het DB model dan?
Een aanpassing aan de DB access functie kan ik me nog voorstellen, maar dan zit je met dezelfde type duplicatie als de normale static_cast.

[ Voor 72% gewijzigd door Olaf van der Spek op 29-07-2009 13:43 ]


Acties:
  • 0 Henk 'm!

Verwijderd

Niet om het een of het ander maar bestaat de long long int weleens in C++?

Ik dacht dat teminste voor C++99 de int altijd machine dependent was en dus 4 chars voor 32bit machines en 8 chars voor 64bit machines. Een int is een verkorte notatie voor long int en long long int bestaat alleen in C, niet C++. Hoewel vrijwel elke moderne compiler hier niet moeilijk overdoet is het niet strict C++ dacht ik.

Ontopic:
Een typedef lijkt mij de simpelste oplossing voor dit probleem maar eigenlijk is hier natuurlijk eerder architectuur probleem omdat je database types niet 1-op-1 op je applicatie aansluiten.

Daarnaast als je dan toch 1 interface naar je database wilt hebben; Zou het een probleem zijn om een groter type dan strikt nodig is te gebruiken zodat je zowel de BigInt als andere integers aankunt? Je zou dan bijvoorbeeld je hele applicatie kunnen standaardiseren op een 64bit integer en dan in je interface 1x casten naar precies dat type. Je interface geeft dat type terug en de rest van je applicatie kan het niet schelen of die integer uit je database komt of uit /dev/random of een oracle machine. Hierkomen typedefs dan goed van pas.

1 type to rule them all. Todat 128bit database machines opduiken wellicht maar 64bit volstaat voor als nog.

Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 17-09 14:05

.oisyn

Moderator Devschuur®

Demotivational Speaker

Verwijderd schreef op woensdag 29 juli 2009 @ 23:48:
Niet om het een of het ander maar bestaat de long long int weleens in C++?
Niet in C++03, maar wel in C99, en ook in C++0x die zo goed als final is (hoewel, je ziet wat er met concepts gebeurd is...). Maar praktisch iedere moderne C++ compiler ondersteunt long long, zoals je zelf ook al zegt een stukje verderop. Veel compilers hebben bovendien al meer C++0x extensies dan alleen de long long.
Ik dacht dat teminste voor C++99 de int altijd machine dependent was en dus 4 chars voor 32bit machines en 8 chars voor 64bit machines.
Nee. Nou bestaat C++99 niet ;), maar de C++ standaard (die leunt op C90) heeft nooit iets gezegd over de grootte van een int, behalve dat hij minstens 16 bits is, groter-gelijk dan een short en kleiner-gelijk dan een long. C99 zegt geloof ik wel dat het typisch een machine word is. Overigens is Windows x64 een LLP64 platform, dus de int en zelfs de long blijven dan 32 bits. Onder linux, wat dacht ik LP64 is, is de int 32 bits maar de long wel 64 bits. Een 64 bits int zul je dus sowieso niet heel snel tegen komen (64 bit arithmetic instructies op AMD64 hebben ook een prefix nodig, ze zijn dus langer dan de 32 bits varianten - 64 bits ints vergroten dus alleen maar je binary footprint terwijl je die 32 extra bits vaak niet eens nodig hebt. En bovendien bestaat er dan geen 32 bits type meer)
Een int is een verkorte notatie voor long int
Nee, een long is een verkorte notatie van (signed) long int. Long en int zijn echter twee verschillende typen. :)

[ Voor 19% gewijzigd door .oisyn op 30-07-2009 00:37 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

Verwijderd

klopt helemaal.

Ik was inderdaad signedness even vergeten aangezien dat geen invloed heeft op de grote en de inhoud van een integer. En volgensmij is het niet perse 16 bits maar eerder 2 chars welke minimaal 8 bits elk moeten zijn.

Ah, C99 natuurlijk. Hoe heet de voorganger van de C++03 specificaties dan ook al weer? stamt toch ook uit 1999 ergens? en was long long ook niet geintroduceerd met C99 en daarom missend in de C++ spec?

Ik ben er toch vrij zeker van dat g++ onder 64bit linux met 64bit compilatie een 64bit int uitspuugt. Mischien dat windows nog ivm backwards compatibiliteit 32bits blijft maar voor g++ is het een optie om 32bit of 64bit executables te maken en de grote van de int veranderd mee. Ik heb dit zelf getest pas nog met SIZEOF(int).

Dat x86_64 een langere opcode gebruikte voor 64bit aritmetic wist ik niet maar dat is een compiler issue eigenlijk. Het zou wel eens intresant zijn te kijken of dat deze instructies ook werkelijk langzamer zijn aangezien met de echte 64bit processors, dus niet de netburst, ook de geheugen bandwijdte, registers en ALU's zijn verbreed. Dit was ook een van de redenen waarom de K8 sneller was, ook in de 32bit modus.

Ik denk echter dat als je je zorgen gaat maken over de grote van je opcodes dat je in de verkeerde taal bezig bent en beter meteen in assembly kunt gaan werken. En tja het kiezen van de juiste integer grote blijft lastig en des te meer reden om met een typedef te werken ipv hardcoded declaraties. Maarja dan moet je wel zinnige namen bedenken zodat de intentie en betekenis van het type duidelijk blijft. En ik krijg het idee dat je met 64bit integers altijd goed zit. Er is mischien een performance penalty maar een integer overflow kan onverwachte bugs creeren en is dus erger. Optimalizeren kan altijd nog dus met een typedef naar een long int of long long int zit je altijd goed wel goed en kan je er later zo nog een short int of zelf een char van maken zonder problemen.

De 8 bytes voor elke pointer is jammer inderdaad maar nou niet meteen een groot probleem. Je moet heel wat pointers hebben voordat je geheugen opraakt. Mischien zouden ze een short pointer kunnen introduceren? Of een soort dual pointer opcode zodat je 2 registers kunt laden uit elk de eerste 4GB geheugen in 1 tick?

Ik maak me meer zorgen over de geheugen latencies voor elke instructie dan de totale geheugen consumptie aangezien geheugen goedkoop is. Performance wordt bepaald door het aantal instructies dat je per seconde afwerkt niet de hoeveeldheid bytes die daarmee gemoeid zijn. PIO is zo 80s, SIMD en DMA is here ;)

Acties:
  • 0 Henk 'm!

  • Punkie
  • Registratie: Oktober 2005
  • Laatst online: 15-08 20:48
Olaf van der Spek schreef op woensdag 29 juli 2009 @ 13:37:
[...]

Totdat je de categorie van een variabele veranderd.
Maar dat doen we niet. Zoals reeds verklaard boven.
Olaf van der Spek schreef op woensdag 29 juli 2009 @ 13:37:
[...]

Wel? Nee, er veranderd niks behalve het type van de variabele.
De "wel" slaat op het wel gelijkwaardig zijn van de oplossingen in termen van programmeergemak. Het uitgangspunt is hier dat het type kan veranderen maar enkel omdat het type van de categorie van de variabele wijzigt en niet omdat de variabele van categorie verandert.
Olaf van der Spek schreef op woensdag 29 juli 2009 @ 13:37:
[...]

Wat zou je willen aanpassen aan het DB model dan?
Een aanpassing aan de DB access functie kan ik me nog voorstellen, maar dan zit je met dezelfde type duplicatie als de normale static_cast.
Maar je cast is dan wel ingetrokken in de functie ipv bij iedere call een cast te schrijven. Wat je minder toetsaanslagen kost en dus gemakkelijker kan zijn in gebruik. Dit staat echter orthogonaal op de template en typedef oplossingen.

MBT aanpassen van het DB model: ik denk dat ik hier wat te voortvarend ben geweest. Want waarom returnt die functie een long long wanneer je een int verwacht?
-Omdat je in de DB een 32 bit int als een 64 bit int opslaat? En je dus 1 functie gebruikt om 2 verschillende DB velden te geven?
-Omdat de access functies geen 32 en 64 bit varianten kennen?
-..
Er van uitgaande dat je een 32 bit waarde altijd kan opslaan in de DB als een 32bit veld en uit de access functies een 32 bit integer krijgt; en dit voor 64 bit waarden , 64 bit velden en 64 bit return values zijn; dan hebben we nooit casts nodig.

Acties:
  • 0 Henk 'm!

  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
.oisyn schreef op donderdag 30 juli 2009 @ 00:18:
Nee. Nou bestaat C++99 niet ;), maar de C++ standaard (die leunt op C90) heeft nooit iets gezegd over de grootte van een int, behalve dat hij minstens 16 bits is, groter-gelijk dan een short en kleiner-gelijk dan een long.
Is het tegenwoordig niet >= 32 bits (in C of in C++)? Dacht dat het ergens geupdate was.
Onder linux, wat dacht ik LP64 is, is de int 32 bits maar de long wel 64 bits.
Linux x64 bedoel je neem ik aan? Linux draait op meer 64-bits platforms.
Een 64 bits int zul je dus sowieso niet heel snel tegen komen (64 bit arithmetic instructies op AMD64 hebben ook een prefix nodig, ze zijn dus langer dan de 32 bits varianten - 64 bits ints vergroten dus alleen maar je binary footprint terwijl je die 32 extra bits vaak niet eens nodig hebt. En bovendien bestaat er dan geen 32 bits type meer)
Ik dacht eigenlijk dat in 64-bits mode de default 64-bits arithmetic was.

Wat is eigenlijk de reden dat long int is toegestaan? Lijkt me een beetje overbodig, long werkt ook gewoon.
En waarom is long long geintroduceerd in plaats van long te vergroten tot 8 bytes?
Officieel staat de grootte van die types niet vast, maar blijkbaar is er genoeg code die aannames doet zodat long niet veranderd kon worden. Gelukkig komen er binnenkort fixed-size int types.

[ Voor 10% gewijzigd door Olaf van der Spek op 30-07-2009 11:48 ]


Acties:
  • 0 Henk 'm!

  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
Verwijderd schreef op donderdag 30 juli 2009 @ 02:30:
Ah, C99 natuurlijk. Hoe heet de voorganger van de C++03 specificaties dan ook al weer? stamt toch ook uit 1999 ergens? en was long long ook niet geintroduceerd met C99 en daarom missend in de C++ spec?
Wikipedia: C++

C++ 98.
Ik ben er toch vrij zeker van dat g++ onder 64bit linux met 64bit compilatie een 64bit int uitspuugt. Mischien dat windows nog ivm backwards compatibiliteit 32bits blijft maar voor g++ is het een optie om 32bit of 64bit executables te maken en de grote van de int veranderd mee. Ik heb dit zelf getest pas nog met SIZEOF(int).
Dat dacht ik dus ook, maar het is niet zo.
De 8 bytes voor elke pointer is jammer inderdaad maar nou niet meteen een groot probleem. Je moet heel wat pointers hebben voordat je geheugen opraakt. Mischien zouden ze een short pointer kunnen introduceren? Of een soort dual pointer opcode zodat je 2 registers kunt laden uit elk de eerste 4GB geheugen in 1 tick?
Short pointers zouden inderdaad best handig zijn als een app toch niet meer dan 4 gb nodig heeft.
Ik maak me meer zorgen over de geheugen latencies voor elke instructie dan de totale geheugen consumptie aangezien geheugen goedkoop is. Performance wordt bepaald door het aantal instructies dat je per seconde afwerkt niet de hoeveeldheid bytes die daarmee gemoeid zijn. PIO is zo 80s, SIMD en DMA is here ;)
Het gaat ook niet zozeer om memory usage maar meer om memory bandbreedte enzo. Caches zijn niet zo groot en als je pointers 2x zo klein zijn scheelt dat gewoon.
Punkie schreef op donderdag 30 juli 2009 @ 10:11:
-Omdat de access functies geen 32 en 64 bit varianten kennen?
Inderdaad. Het type in de DB is natuurlijk ook gewoon int. Als ik een int en een long long access functie gebruikte, had ik ook geen probleem gehad. Maar ja, het nadeel daarvan is hetzelfde als de cast.

[ Voor 10% gewijzigd door Olaf van der Spek op 30-07-2009 11:46 ]


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 17-09 14:05

.oisyn

Moderator Devschuur®

Demotivational Speaker

Verwijderd schreef op donderdag 30 juli 2009 @ 02:30:
Ik denk echter dat als je je zorgen gaat maken over de grote van je opcodes dat je in de verkeerde taal bezig bent en beter meteen in assembly kunt gaan werken.
Niemand beweert hier zich zorgen te maken over de lengte van je opcodes. Ik had het over een (mogelijke) beweegreden van een compiler implementatie om een int op 32 bits te houden.
Ik maak me meer zorgen over de geheugen latencies voor elke instructie dan de totale geheugen consumptie aangezien geheugen goedkoop is.
Geheugen wel, cache niet. Meer geheugen betekent een minder efficiente cache en dus hogere latencies.
Performance wordt bepaald door het aantal instructies dat je per seconde afwerkt niet de hoeveeldheid bytes die daarmee gemoeid zijn.
Wel dus :). Instruction cache.
Olaf van der Spek schreef op donderdag 30 juli 2009 @ 11:40:
[...]

Is het tegenwoordig niet >= 32 bits (in C of in C++)? Dacht dat het ergens geupdate was.
C99 volgens mij, maar C++ leunt niet op C99, vandaar.
Linux x64 bedoel je neem ik aan? Linux draait op meer 64-bits platforms.
Ja idd, ik had het puur over x86 :)
Ik dacht eigenlijk dat in 64-bits mode de default 64-bits arithmetic was.
Nope.
Wat is eigenlijk de reden dat long int is toegestaan? Lijkt me een beetje overbodig, long werkt ook gewoon.
Geen idee. Hetzelfde geldt voor short trouwens, wat eigenlijk short int is.
En waarom is long long geintroduceerd in plaats van long te vergroten tot 8 bytes?
Waarschijnlijk omdat (voor het 64 bits tijdperk) een short altijd typisch 16 bits was en een long 32 bits, en een int afhing van van de CPU (16 of 32 bits)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

Verwijderd

Als ik om een 64bits int vraag moet een compiler wel heel gek zijn om mij een 32bits integer te geven. Dan had ik wel om een short gevraagd. Nog een reden om typedefs te gebruiken want in 64bits compiles is een long int weer het zelfde als een long long int in 32bits compilatie. Met een simpele preprocessor instructie kun je dan er dan voor zorgen dat je int grootes het zelfde blijven tenzij je dit expliciet aangeeft.

Met geheugen bedoelde ik het hele geheugen systeem dus inclusief caches. De x86 specs maken geen onderscheid of dat geheugen nou op een cache, ddr ram chip of zelf op papier staat uitgeprint en weer wordt ingescanned. Het is de taak van de geheugen controller en prefetchers om te zorgen dat de data daar is wanneer het nodig is.

Toch moet je het best bont maken wil je je instruction cache verzuipen. Er is ook netzoals met je data cache een prediction prefetcher of hoe dat ding ook heet en aangezien instructies alleen bij long jumps onverspelbaar zijn moet je wel heel snel heel veel onverwachte long jumps maken wil de prefetcher de nieuwe instructie page niet al hebben ingeladen ten tijde van de jump. Dat wijst vaak eerder op slecht geschreven code. Als je multi-threaded schrijft neemt ook de last op de instructie cache af omdat elke core zijn eigen instructie cache heeft en 2 threads op 2 cores dus praktisch elk hun eigen cache hebben.

De moderne CPU is eigenlijk steeds meer een COP: Central Organizer Unit. Met steeds betere SIMD instructies en DMA. Zelfs de GPU wordt nu meer general purpose en toekomstige CPU's zullen steeds meer cores hebben. Het is een kwestie van divide en conquer: door je data logische te partitioneren, asynchrone te bewerken over meerdere cores in een logische voorspelbaar patroon kun je maximale througput halen.

De kunst van het hedendaags programmeren is door zoveel mogelijk naast elkaar ipv achter elkaar te doen. Serialiteit zou je moeten vermijden en als het moet doe het op een manier waar prefetchers optimaal gebruik van kunnen maken. Het is kwestie van je programma goed opzetten of zoals ik altijd zeg: bezint eer ge begint.

Tuurlijk is er een limiet. Ik ken amdale's law ook maar ik weet ook dat het een stuk makkelijker is om geheugen bandwijdte te viervoudigen, caches 2x zo groot te maken dan om de instructies/clock te verdubbelen. De Hypertransport architectuur van de Opteron doet precies dit. Voeg meer CPU's toe en je vergroot niet alleen het aantal geheugen controllers en daarmee je totale bandwijdte. Ook het aantal caches, ALUs, FPUs, prefetchers, etc. Het is de truuk om deze NUMA archictuur uit te buiten zoals gezegd: divide en conquer.

Alleen voorspelbare, logische gepartitioneerde programma's kunnen hier optimaal gebruik van maken en deze trend is nog lang niet over want tegen de tijd dat de Core i19 @ 8Ghz hier is heeft deze ook 64 core's.

En ik heb het zojuist nog eens even uitgeprobeerd, een simpel C++ programma, onder Ubuntu 8.10 x86_64 met g++ met de default flags vertelt mij dat SIZEOF(int) 8 bytes is. Maar ik weet dat sommige linux distro's de default compile flags zo hebben staan dat er 32bits int worden gebruikt dus dit is inderdaad echt een compile optie.

Acties:
  • 0 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 22:22
Verwijderd schreef op donderdag 30 juli 2009 @ 23:58:
En ik heb het zojuist nog eens even uitgeprobeerd, een simpel C++ programma, onder Ubuntu 8.10 x86_64 met g++ met de default flags vertelt mij dat SIZEOF(int) 8 bytes is.
Dat is onzin; vziw gebruiken alle 64-bit Linux distro's dezelfde ABI en die is gebaseerd op het LP64 model. Ik nodig je uit om het volgende programma eens uit te proberen:
C:
1
2
3
4
5
#include <stdio.h>
int main() {
  printf("%d %d %d\n", sizeof(int), sizeof(long), sizeof(void*));
  return 0;
}

cc test.c && ./a.out

Dan zul je zien dat de uitvoer 4 8 8 is en niet 8 8 8.
.oisyn schreef op donderdag 30 juli 2009 @ 00:18:
Overigens is Windows x64 een LLP64 platform, dus de int en zelfs de long blijven dan 32 bits.
Argh! Dan is er dus helemaal geen semi-portable manier om een pointer-sized integer te krijgen die ook onder Windows werkt?! Ik zou intptr_t uit <stdint.h> voorstellen ware het niet dat MSVC nog steeds geen C99 support en ook geen <stdint.h> shipt.

[ Voor 24% gewijzigd door Soultaker op 31-07-2009 01:16 ]


Acties:
  • 0 Henk 'm!

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Soultaker schreef op vrijdag 31 juli 2009 @ 01:14:
Argh! Dan is er dus helemaal geen semi-portable manier om een pointer-sized integer te krijgen die ook onder Windows werkt?! Ik zou intptr_t uit <stdint.h> voorstellen ware het niet dat MSVC nog steeds geen C99 support en ook geen <stdint.h> shipt.
<cstdint> std::tr1::int64_t? Anders boost/cstdint.hpp
Olaf van der Spek schreef op donderdag 30 juli 2009 @ 11:45:
Short pointers zouden inderdaad best handig zijn als een app toch niet meer dan 4 gb nodig heeft.
Zeker. Ik moest laatst een kd-tree implementeren, en dat kan netjes in 8 bytes per node op een 32bit systeem, maar als je dat naief doet op een 64bit systeem worden het er 12. Dat is een enorme performance hit (over cache efficiency gesproken... ik lees al een aantal keer dat je geheugen toch niet zo snel opraakt, maar daar gaat het idd niet om. Dit is een goed voorbeeld daarvan; raytracing performance hangt zwaar op de cache en hoe kleiner je kd-tree nodes, hoe sneller het gaat, simpelweg omdat je meer nodes kan cachen. Een 64bit pointer is dan funest)

[ Voor 54% gewijzigd door Zoijar op 31-07-2009 01:48 ]


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 17-09 14:05

.oisyn

Moderator Devschuur®

Demotivational Speaker

Custom allocator die zorgt dat de nodes uit dezelfde (max 4 GB) chunk komen en dan relatieve offsets opslaan dmv 32 bits ints (danwel vanaf de start van de buffer, danwel vanaf de huidige node) is evt nog een optie. Wel een extra level aan indirectie though

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

.oisyn schreef op vrijdag 31 juli 2009 @ 01:47:
Custom allocator die zorgt dat de nodes uit dezelfde (max 4 GB) chunk komen en dan relatieve offsets opslaan dmv 32 bits ints (danwel vanaf de start van de buffer, danwel vanaf de huidige node) is evt nog een optie. Wel een extra level aan indirectie though
Ik heb gewoon geindexed in een vector, omdat die gegarandeerd contiguous is. Van wat ik weet is een offset lookup net zo snel als een absolute. (uiteraard is het in CUDA weer een verhaal apart :P )

[ Voor 5% gewijzigd door Zoijar op 31-07-2009 01:56 ]


Acties:
  • 0 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 22:22
Zoijar schreef op vrijdag 31 juli 2009 @ 01:34:
<cstdint> std::tr1::int64_t? Anders boost/cstdint.hpp
Op zich goede suggesties, maar het ging me ook om C, niet C++ (ja, verkeerde topic eigenlijk) en int64_t is juist exact 64-bit ongeacht het platform...

Volgens mij zijn platform-specifieke typedefs de enige zinnige oplossing op dit moment, wat jammer is, want het heeft wel wat om pointers van/naar long te kunnen casten.

[ Voor 4% gewijzigd door Soultaker op 31-07-2009 02:15 ]


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 17-09 14:05

.oisyn

Moderator Devschuur®

Demotivational Speaker

Vziw past een pointer altijd in een size_t en een ptrdiff_t, waarbij de ene unsigned is en de andere signed.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • H!GHGuY
  • Registratie: December 2002
  • Niet online

H!GHGuY

Try and take over the world...

Verwijderd schreef op donderdag 30 juli 2009 @ 23:58:
Toch moet je het best bont maken wil je je instruction cache verzuipen. Er is ook netzoals met je data cache een prediction prefetcher of hoe dat ding ook heet en aangezien instructies alleen bij long jumps onverspelbaar zijn moet je wel heel snel heel veel onverwachte long jumps maken wil de prefetcher de nieuwe instructie page niet al hebben ingeladen ten tijde van de jump. Dat wijst vaak eerder op slecht geschreven code. Als je multi-threaded schrijft neemt ook de last op de instructie cache af omdat elke core zijn eigen instructie cache heeft en 2 threads op 2 cores dus praktisch elk hun eigen cache hebben.
Met 8 threads op 2 cores verhoogt de druk op je instruction cache net...
De moderne CPU is eigenlijk steeds meer een COP: Central Organizer Unit. Met steeds betere SIMD instructies en DMA.
SIMD en DMA zijn zo 90's. Ja we hebben ze nodig, maar elk zichzelf respecterende processor/periferie supporteert deze technieken waar nodig/toepasbaar.
Async I/O of in een aparte thread en heavy-lifting in meerdere threads doen zoals je zegt. Samen met hyperthreading zorg je dan voor beter gebruik van de core want als 1 thread stallt/blockt dan staan er wel 3 te wachten om verder te werken.
Het is de truuk om deze NUMA archictuur uit te buiten zoals gezegd: divide en conquer.
Programmeren voor NUMA is helemaal niet zo eenvoudig. Bovendien kan je OS maar beter een handje helpen of het is helemaal huilen met de pet op qua performance.

ASSUME makes an ASS out of U and ME


Acties:
  • 0 Henk 'm!

  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
Soultaker schreef op vrijdag 31 juli 2009 @ 02:03:
Volgens mij zijn platform-specifieke typedefs de enige zinnige oplossing op dit moment, wat jammer is, want het heeft wel wat om pointers van/naar long te kunnen casten.
Kun je het niet andersom doen? Altijd een pointer gebruiken en de long naar een pointer casten? En weer terug als je toch de long nodig hebt.
.oisyn schreef op vrijdag 31 juli 2009 @ 02:19:
Vziw past een pointer altijd in een size_t en een ptrdiff_t, waarbij de ene unsigned is en de andere signed.
Wordt dat gegarandeerd?

[ Voor 22% gewijzigd door Olaf van der Spek op 01-08-2009 14:04 ]


  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
Nog even een vervolg op type duplication. Voor een iteratie over een container gebruik ik heel vaak
C++:
1
2
3
4
5
typedef vector<int> T;
T t;
for (T::const_iterator i = t.begin(); i != t.end(); i++)
{
}

Waarom is het eigenlijk niet mogelijk t::const_iterator te gebruiken zodat je geen aparte typedef nodig hebt? Dus je gebruikt :: op de variabele en niet op het type.

[ Voor 11% gewijzigd door Olaf van der Spek op 17-09-2009 16:28 ]


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 17-09 14:05

.oisyn

Moderator Devschuur®

Demotivational Speaker

Dunno, mail bjarne@stroustrup.com ;)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • roy-t
  • Registratie: Oktober 2004
  • Laatst online: 08-09 11:33
omdat '::' de scope resolution operator is en niet de 'get the type of this variable and resolute the scope of that type' operator? :P

~ Mijn prog blog!


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 17-09 14:05

.oisyn

Moderator Devschuur®

Demotivational Speaker

Het zal wel te maken hebben met het feit dat types in de eerste pass al geresolved moeten worden omdat ze nodig zijn voor de parser (oftewel, de tokenizer geeft voor identifiers die types zijn andere tokens dan voor identifiers die geen types zijn), maar dat non-type definities zelf pas tijdens de semantische analyse aan bod komen. Op het moment dat hij t::bla tegen komt, weet ie nog niet wat 't' eigenlijk voor moet stellen - behalve dan dat het geen type is. Zie dit codevoorbeeld:

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
struct S
{
    void foo1()
    {
         NestedType v; // mag niet, NestedType is nog niet bekend 
         u.i = 34; // mag weer wel, dit wordt pas geanalyseerd na de volledige class definitie.
    }

    struct NestedType
    {
        int i;
        typedef int * iterator;
    };

    void foo2()
    {
         NestedType v; // nu mag het wel
    }

    NestedType u;
};


Vergelijkbaar kun je dus ook niet 'typedef u::iterator my_iterator' doen in S of in S::foo1()

[ Voor 7% gewijzigd door .oisyn op 17-09-2009 17:22 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 22:22
Toch support b.v. GCC een typeof() operator (een extensie) dus het kan allemaal wel. En was voor C++0x niet voorgesteld om dit soort dingen te kunnen doen:
C++:
1
auto it = v.begin(); 

Lijkt me dat je daarbij het type van `it' ook pas kunt bepalen in de tweede fase, als je de expressie v.begin() geanalyzeerd hebt.

Weet trouwens niet of de taal C++ überhaupt op dit niveau (vanuit perspectief van de compiler) gespecifieerd is? (Kan misschien niet anders met zo'n complexe moloch.)

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 17-09 14:05

.oisyn

Moderator Devschuur®

Demotivational Speaker

Soultaker schreef op donderdag 17 september 2009 @ 17:25:
Toch support b.v. GCC een typeof() operator (een extensie) dus het kan allemaal wel.
En was voor C++0x niet voorgesteld om dit soort dingen te kunnen doen:
C++:
1
auto it = v.begin(); 
Ja maar dan zijn ze ook pas nodig bij de semantische analyse :). Dit kan bijv. niet in gcc:
C++:
1
2
3
4
struct S { typedef void * ptr; };
S s;
typeof(s)::ptr myptr; // error
typedef typeof(s)::ptr ptr; // error

Hetzelfde kan ook niet met decltype in C++0x.

.edit: hmm, maar dit kan dan weer wel:
C++:
1
2
typedef decltype(s) S2;
S2::ptr ptr;

Raar dat daar geen typename nodig is, zoals in templates ook het geval is.

.edit2: hmm, wellicht moet ik de standaard nog even induiken, want dit geeft in MSVC++ 2010 ook geen error meer:
C++:
1
2
3
4
5
6
7
template<class T> struct S
{
    void foo()
    {
        T::ptr i2;
    }
};

Waar daar voorheen typename nodig was.
En ik kan me niet herinneren dat ze die regels gerelaxeerd hebben :). Aan de andere kant zou dat wel logisch zijn als ze decltype volledig willen supporten.

[ Voor 34% gewijzigd door .oisyn op 17-09-2009 17:56 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
.oisyn schreef op donderdag 17 september 2009 @ 17:20:
Het zal wel te maken hebben met het feit dat types in de eerste pass al geresolved moeten worden omdat ze nodig zijn voor de parser (oftewel, de tokenizer geeft voor identifiers die types zijn andere tokens dan voor identifiers die geen types zijn), maar dat non-type definities zelf pas tijdens de semantische analyse aan bod komen. Op het moment dat hij t::bla tegen komt, weet ie nog niet wat 't' eigenlijk voor moet stellen - behalve dan dat het geen type is. Zie dit codevoorbeeld:
Met andere woorden, als het toegestaan zou zijn zou het niet meer te parsen zijn? Dat zou ik zo 1 2 3 niet weten, maar het lijkt me stug.

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 17-09 14:05

.oisyn

Moderator Devschuur®

Demotivational Speaker

Het zou moeilijk te parsen zijn. Waarom denk je dat typename verplicht is in templates voor dependent types? Of dat je een geneste template niet mag afsluiten met >>? Exact dezelfde reden.

Let wel, dat waren regels van meer dan 10 jaar oud. De praktijk wees uit dat compiler implementors het er eigenlijk helemaal niet zo heel moeilijk mee hadden. typename was nooit verplicht in MSVC++, dat is puur toegevoegd om meer compliant te zijn. Ook de >> voor template afsluiting hadden veel implementors al zelf geïmplementeerd, en die regel is dan ook opgenomen in C++0x

[ Voor 63% gewijzigd door .oisyn op 17-09-2009 19:30 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
Als het onbekend is en het wordt gebruikt als type, is het dan niet veilig aan te nemen dat het inderdaad een type is?

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 17-09 14:05

.oisyn

Moderator Devschuur®

Demotivational Speaker

Het punt is dat je niet weet wanneer iets gebruikt wordt als type. Iets als bla(3) kan een functieaanroep zijn, of het aanmaken van een object van het type bla.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
Dat is waar, maar dat kun je in een latere stage uitzoeken lijkt me.

Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 17-09 14:05

.oisyn

Moderator Devschuur®

Demotivational Speaker

Dat het op te lossen is was natuurlijk allang duidelijk. De kern van de zaak is echter dat de standaard dergelijke complexiteit niet wil(de) opleggen aan de implementors.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.

Pagina: 1