[Tipps & Tricks] bad programming

Programmiersprachen, APIs, Bibliotheken, Open Source Engines, Debugging, Quellcode Fehler und alles was mit praktischer Programmierung zu tun hat.
Benutzeravatar
Zudomon
Establishment
Beiträge: 2259
Registriert: 25.03.2009, 07:20
Kontaktdaten:

Re: [Tipps & Tricks] bad programming

Beitrag von Zudomon »

Da hab ich doch etwas viele "end;" am Ende :D

Code: Alles auswählen

procedure UpdateRegister;
var
  i: Integer;
begin
  if state_Pass<0 then showmsg('Kein Pass aktiviert!');

  with D3DDevice do begin
    with Pass[state_Pass] do begin
      for i := 0 to high(PassSlot) do with PassSlot[i] do begin
        with ShaderConstant[Constant] do begin
          case ShaderType of
            st_VertexShader: begin
              case TypeOf of
                sct_Matrix4: SetVertexShaderConstantF(RegSlot, @Data[0], 4);
              end;
            end;
            st_PixelShader: begin
              case TypeOf of
                sct_Matrix4: SetPixelShaderConstantF(RegSlot, @Data[0], 4);
              end;
            end;
          end;
        end;
      end;
    end;
  end;
end;
Benutzeravatar
Chromanoid
Moderator
Beiträge: 4273
Registriert: 16.10.2002, 19:39
Echter Name: Christian Kulenkampff
Wohnort: Lüneburg

Re: [Tipps & Tricks] bad programming

Beitrag von Chromanoid »

wie sind da die regeln für groß- und kleinschreibung? Also delphi ist das ja egal, aber dem leser nicht...
Benutzeravatar
Zudomon
Establishment
Beiträge: 2259
Registriert: 25.03.2009, 07:20
Kontaktdaten:

Re: [Tipps & Tricks] bad programming

Beitrag von Zudomon »

Chromanoid hat geschrieben:wie sind da die regeln für groß- und kleinschreibung? Also delphi ist das ja egal, aber dem leser nicht...
Wie du schon sagt, Delphi ist das egal... und ich habe mir da halt meinen Stil angewöhnt...
Benutzeravatar
CodingCat
Establishment
Beiträge: 1857
Registriert: 02.03.2009, 21:25
Wohnort: Student @ KIT
Kontaktdaten:

Re: [Tipps & Tricks] bad programming

Beitrag von CodingCat »

Wie zu allen Codebeispielen fällt mir auch zu diesem nur wieder ein: Delphi ist ganz offensichtlich die grässlichste Sprache der Welt. :P
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
Benutzeravatar
FlashbackOwl
Beiträge: 76
Registriert: 13.10.2011, 17:14

Re: [Tipps & Tricks] bad programming

Beitrag von FlashbackOwl »

Nee, Factor ist offensichtlich die grässlichste Sprache der Welt !
Beispiel vom HelloWorld- Programm(Hoffe das stimmt so :/ )

Code: Alles auswählen

USE: io
IN: hello-world

: hello ( -- ) "Hello, World!" print ;

MAIN: hello
Linux wird nie das meistinstallierte Betriebssystem sein, wenn man bedenkt, wie oft man Windows neu installieren muss...
hagbard
Beiträge: 66
Registriert: 05.08.2010, 23:54

Re: [Tipps & Tricks] bad programming

Beitrag von hagbard »

Zudomon hat geschrieben:Da hab ich doch etwas viele "end;" am Ende :D

Code: Alles auswählen

procedure UpdateRegister;
var
  i: Integer;
begin
  if state_Pass<0 then showmsg('Kein Pass aktiviert!');

  with D3DDevice do begin
    with Pass[state_Pass] do begin
      for i := 0 to high(PassSlot) do with PassSlot[i] do begin
        with ShaderConstant[Constant] do begin
          case ShaderType of
            st_VertexShader: begin
              case TypeOf of
                sct_Matrix4: SetVertexShaderConstantF(RegSlot, @Data[0], 4);
              end;
            end;
            st_PixelShader: begin
              case TypeOf of
                sct_Matrix4: SetPixelShaderConstantF(RegSlot, @Data[0], 4);
              end;
            end;
          end;
        end;
      end;
    end;
  end;
end;
Wenn jemand dir dochmal einen Rat geben kann: Lass die Finger von 'With', dass ist ein Designfehler der Sprache und führt meisten zu unleserlichen Code auch wenn du weniger tippen musst. *duck*
Benutzeravatar
Zudomon
Establishment
Beiträge: 2259
Registriert: 25.03.2009, 07:20
Kontaktdaten:

Re: [Tipps & Tricks] bad programming

Beitrag von Zudomon »

hagbard hat geschrieben:
Zudomon hat geschrieben:Da hab ich doch etwas viele "end;" am Ende :D

Code: Alles auswählen

procedure UpdateRegister;
var
  i: Integer;
begin
  if state_Pass<0 then showmsg('Kein Pass aktiviert!');

  with D3DDevice do begin
    with Pass[state_Pass] do begin
      for i := 0 to high(PassSlot) do with PassSlot[i] do begin
        with ShaderConstant[Constant] do begin
          case ShaderType of
            st_VertexShader: begin
              case TypeOf of
                sct_Matrix4: SetVertexShaderConstantF(RegSlot, @Data[0], 4);
              end;
            end;
            st_PixelShader: begin
              case TypeOf of
                sct_Matrix4: SetPixelShaderConstantF(RegSlot, @Data[0], 4);
              end;
            end;
          end;
        end;
      end;
    end;
  end;
end;
Wenn jemand dir dochmal einen Rat geben kann: Lass die Finger von 'With', dass ist ein Designfehler der Sprache und führt meisten zu unleserlichen Code auch wenn du weniger tippen musst. *duck*
Das schlimme am "with" ist, dass es Fehler produzieren kann, wenn nämlich sich das with z.B. auf ein Element aus einem dynamischen Array bezieht, welches dann intern vergrößert wird... ich meine, damit kommt der nicht klar...
Naja, aber ich bin dankbar für das with, ansonsten gibt es ewig lange Konstrukte und meine Zeilen würden nicht mehr vollständig auf den Bildschirm passen... und dann verliere ich wirklich die Übersicht.

Es ist schade, dass es keine Defines gibt, sonst könnte man da nämlich auch damit abkürzen... in C++ hab ich damit richtig dreckig programmiert...

Erstmal schöne 1D-, 2D- und 3D-Schleifen

Code: Alles auswählen

#define forExt(i, t)              for(int (i)=0; (i)<int(t); (i)++)
#define forExt2D(i,j,t1,t2)       forExt(i, t1) forExt(j, t2)
#define forExt3D(i,j,k,t1,t2,t3)  forExt2D(i,j,t1,t2) forExt(k, t3)
Und dann daraus Vektor und Matrix Klassen bauen:

Code: Alles auswählen

#define VEC1(exp)  TVec3 r; forExt(i, 3) r.v[i]=exp; return r;
#define VEC2(exp)  forExt(i, 3) v[i]exp; return *this;

class TVec3{
  public:
    float v[3];
    TVec3&operator = (float s)   { forExt(i, 3) v[i]=s; return *this; };
    TVec3 operator - ()          { VEC1( -v[i]         ) };
    TVec3 operator - (TVec3 opp) { VEC1( v[i]-opp.v[i] ) };
    TVec3 operator - (float s)   { VEC1( v[i]-s        ) };
    TVec3 operator + (TVec3 opp) { VEC1( v[i]+opp.v[i] ) };
    TVec3 operator + (float s)   { VEC1( v[i]+s        ) };
    TVec3 operator * (float s)   { VEC1( v[i]*s        ) };
    TVec3 operator / (float s)   { DIV0( s, return operator=(0); , return operator*(1.0/s); ) };
    TVec3&operator -=(TVec3 opp) { VEC2( -=opp.v[i]    ) };
    TVec3&operator -=(float s)   { VEC2( -=s           ) };
    TVec3&operator +=(TVec3 opp) { VEC2( +=opp.v[i]    ) };
    TVec3&operator +=(float s)   { VEC2( +=s           ) };
    TVec3&operator *=(float s)   { VEC2( *=s           ) };
    TVec3&operator /=(float s)   { DIV0( s, return *this; , VEC2( /=s; ) ) };
    float&operator [](int index) { return v[index]; };
    float lngSQ()                { return sqr(v[0])+sqr(v[1])+sqr(v[2]); };
    float lng()                  { return sqrt(lngSQ()); };
    void writeTo( char *p )      { *(p++)=_Byte(v[0]); *(p++)=_Byte(v[1]); *p=_Byte(v[2]); } ;
};

TVec3 crt(float a,  float b,  float c)      { TVec3 r={a,b,c}; return r; };
float dot(TVec3 v1, TVec3 v2)               { float r=0; forExt(i,3) r+=v1[i]*v2[i]; return r; };
TVec3 crs(TVec3 v1, TVec3 v2)               { TVec3 r; forExt(i,3) r.v[i]=v1[(i+1)%3]*v2[(i+2)%3]-v1[(i+2)%3]*v2[(i+1)%3]; return r; };
TVec3 nrm(TVec3 v)                          { return v / v.lng(); }
TVec3 lrp(TVec3 v1, TVec3 v2, float s)      { TVec3 r; forExt(i,3)r.v[i]=v1[i]+s*(v2[i]-v1[i]); return r; };
TVec3 normal(TVec3 v1, TVec3 v2, TVec3 v3)  { return crs(v2-v1, v3-v1); }
TVec3 sat(TVec3 v)                          { VEC1( sat(v[i]) ) };

bool same(TVec3*v1, TVec3*v2, float s)      { return (*v1-*v2).lng()<s; };

TVec3 min(TVec3 v1, TVec3 v2)               { VEC1( min(v1[i], v2[i]) ) };
TVec3 max(TVec3 v1, TVec3 v2)               { VEC1( max(v1[i], v2[i]) ) };
TVec3 min(TVec3 v,  float s)                { VEC1( min(v[i],s) ) };
TVec3 max(TVec3 v,  float s)                { VEC1( max(v[i],s) ) };

TVec3 reflect(TVec3 i, TVec3 n)             { return i-(n*dot(i,n)*2); }
TVec3 refract(TVec3 i, TVec3 n, float ind)  { float w,k; w=-(dot(i,n)*ind); k=1.0+(w-ind)*(w+ind);
                                              return k>-ZERO_TOLERANCE?i*ind+n*(w-sqrt(k)):reflect(i, n); }

TVec3 barycentric(TVec3* v1, TVec3* v2, TVec3* v3, float f, float g)  { return *v1 + (*v2-*v1)*f + (*v3-*v1)*g; };
float dist_point_line(TVec3 v, TVec3 lpos, TVec3 ldir)                { return crs(v-lpos,ldir).lng()/ldir.lng(); };
float projdist_point_line(TVec3 v, TVec3 lpos, TVec3 ldir)            { return dot(v-lpos,ldir); };

#undef VEC1
#undef VEC2
//---------------------------------------------------------------------------

class TMatrix4x4 {
  public:
    float m[16];
    TMatrix4x4&operator = (float s) { forExt(i, 16) m[i]=s; return *this; };
    TMatrix4x4 operator * (TMatrix4x4 mat) { TMatrix4x4 r; r=0; forExt3D(i,j,k,4,4,4) r.m[i*4+j]+=m[k*4+j]*mat.m[i*4+k]; return r; };
    TMatrix4x4&operator *=(TMatrix4x4 mat) { TMatrix4x4 r=*this; *this=0; forExt3D(i,j,k,4,4,4) m[i*4+j]+=r.m[k*4+j]*mat.m[i*4+k]; return *this; };
    TVec3 getAxisX(){ return crt(m[0], m[4], m[8]); };
    TVec3 getAxisY(){ return crt(m[1], m[5], m[9]); };
    TVec3 getAxisZ(){ return crt(m[2], m[6], m[10]); };
    TVec3 getPos()  { return crt(m[3], m[7], m[11]); };
    TVec3 transformCoord(TVec3 v) { TVec3 r=transformNormal(v); forExt(i,3)r[i]+=m[i*4+3]; return r; };
    TVec3 transformNormal(TVec3 v) { TVec3 r; r=0; forExt2D(i,j,3,3)r.v[i]+=v[j]*m[i*4+j]; return r; };
};

TMatrix4x4 matScaling(TVec3 v) { TMatrix4x4 m={v[0],0,0,0,0,v[1],0,0,0,0,v[2],0,0,0,0,1}; return m; };
TMatrix4x4 matScaling(float s) { TMatrix4x4 m={s,0,0,0,0,s,0,0,0,0,s,0,0,0,0,1}; return m; };
TMatrix4x4 matRot(float, TVec3);
TMatrix4x4 matRotX(float a) { TMatrix4x4 m={1,0,0,0,0,cos(a),-sin(a),0,0,sin(a),cos(a),0,0,0,0,1}; return m; };
TMatrix4x4 matRotY(float a) { TMatrix4x4 m={cos(a),0,sin(a),0,0,1,0,0,-sin(a),0,cos(a),0,0,0,0,1}; return m; };
TMatrix4x4 matRotZ(float a) { TMatrix4x4 m={cos(a),-sin(a),0,0,sin(a),cos(a),0,0,0,0,1,0,0,0,0,1}; return m; };
TMatrix4x4 matRotZXY(TVec3 v) { return matRotZ(v[2])*matRotX(v[0])*matRotY(v[1]); };
TMatrix4x4 matIdentity() { TMatrix4x4 m={1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1}; return m; };
TMatrix4x4 matTranslation(TVec3 v) { TMatrix4x4 m={1,0,0,v[0],0,1,0,v[1],0,0,1,v[2],0,0,0,1}; return m; };
TMatrix4x4 transpose(TMatrix4x4 m) { TMatrix4x4 r; forExt2D(i,j,4,4)r.m[i*4+j]=m.m[j*4+i]; return r; };
Zuletzt geändert von Zudomon am 22.10.2011, 23:11, insgesamt 1-mal geändert.
j.klugmann
Establishment
Beiträge: 201
Registriert: 07.07.2010, 13:00
Kontaktdaten:

Re: [Tipps & Tricks] bad programming

Beitrag von j.klugmann »

CodingCat hat geschrieben:Wie zu allen Codebeispielen fällt mir auch zu diesem nur wieder ein: Delphi ist ganz offensichtlich die grässlichste Sprache der Welt. :P
Modernes Delphi bietet durchaus alle "modernen" Features, die man von C++ kennt und ist wesentlich angenehmer zu lesen und zu programmieren. :D
Imaging-Software und bald auch Middleware: http://fd-imaging.com
hagbard
Beiträge: 66
Registriert: 05.08.2010, 23:54

Re: [Tipps & Tricks] bad programming

Beitrag von hagbard »

Naja also wenn es der Lesbarkeit dient verwende ich dann lieber temporäre Variablen (bei größeren Datenstrukturen meinetwegen auch als Zeiger realisiert) bevor ich mich mit den Nebeneffekten von 'with' oder Makros rumschlagen muss. Ist klar dass kann Performance kosten aber wir wissen ja "premature optimization is the root of all evil" ;)
Benutzeravatar
BeRsErKeR
Establishment
Beiträge: 689
Registriert: 27.04.2002, 22:01

Re: [Tipps & Tricks] bad programming

Beitrag von BeRsErKeR »

Zudomon hat geschrieben:Es ist schade, dass es keine Defines gibt, sonst könnte man da nämlich auch damit abkürzen... in C++ hab ich damit richtig dreckig programmiert...

Erstmal schöne 1D-, 2D- und 3D-Schleifen

Code: Alles auswählen

#define forExt(i, t)              for(int (i)=0; (i)<int(t); (i)++)
#define forExt2D(i,j,t1,t2)       forExt(i, t1) forExt(j, t2)
#define forExt3D(i,j,k,t1,t2,t3)  forExt2D(i,j,t1,t2) forExt(k, t3)
Und dann daraus Vektor und Matrix Klassen bauen:

Code: Alles auswählen

#define VEC1(exp)  TVec3 r; forExt(i, 3) r.v[i]=exp; return r;
#define VEC2(exp)  forExt(i, 3) v[i]exp; return *this;

class TVec3{
  public:
    float v[3];
    TVec3&operator = (float s)   { forExt(i, 3) v[i]=s; return *this; };
    TVec3 operator - ()          { VEC1( -v[i]         ) };
    TVec3 operator - (TVec3 opp) { VEC1( v[i]-opp.v[i] ) };
    TVec3 operator - (float s)   { VEC1( v[i]-s        ) };
    TVec3 operator + (TVec3 opp) { VEC1( v[i]+opp.v[i] ) };
    TVec3 operator + (float s)   { VEC1( v[i]+s        ) };
    TVec3 operator * (float s)   { VEC1( v[i]*s        ) };
    TVec3 operator / (float s)   { DIV0( s, return operator=(0); , return operator*(1.0/s); ) };
    TVec3&operator -=(TVec3 opp) { VEC2( -=opp.v[i]    ) };
    TVec3&operator -=(float s)   { VEC2( -=s           ) };
    TVec3&operator +=(TVec3 opp) { VEC2( +=opp.v[i]    ) };
    TVec3&operator +=(float s)   { VEC2( +=s           ) };
    TVec3&operator *=(float s)   { VEC2( *=s           ) };
    TVec3&operator /=(float s)   { DIV0( s, return *this; , VEC2( /=s; ) ) };
    float&operator [](int index) { return v[index]; };
    float lngSQ()                { return sqr(v[0])+sqr(v[1])+sqr(v[2]); };
    float lng()                  { return sqrt(lngSQ()); };
    void writeTo( char *p )      { *(p++)=_Byte(v[0]); *(p++)=_Byte(v[1]); *p=_Byte(v[2]); } ;
};

TVec3 crt(float a,  float b,  float c)      { TVec3 r={a,b,c}; return r; };
float dot(TVec3 v1, TVec3 v2)               { float r=0; forExt(i,3) r+=v1[i]*v2[i]; return r; };
TVec3 crs(TVec3 v1, TVec3 v2)               { TVec3 r; forExt(i,3) r.v[i]=v1[(i+1)%3]*v2[(i+2)%3]-v1[(i+2)%3]*v2[(i+1)%3]; return r; };
TVec3 nrm(TVec3 v)                          { return v / v.lng(); }
TVec3 lrp(TVec3 v1, TVec3 v2, float s)      { TVec3 r; forExt(i,3)r.v[i]=v1[i]+s*(v2[i]-v1[i]); return r; };
TVec3 normal(TVec3 v1, TVec3 v2, TVec3 v3)  { return crs(v2-v1, v3-v1); }
TVec3 sat(TVec3 v)                          { VEC1( sat(v[i]) ) };

bool same(TVec3*v1, TVec3*v2, float s)      { return (*v1-*v2).lng()<s; };

TVec3 min(TVec3 v1, TVec3 v2)               { VEC1( min(v1[i], v2[i]) ) };
TVec3 max(TVec3 v1, TVec3 v2)               { VEC1( max(v1[i], v2[i]) ) };
TVec3 min(TVec3 v,  float s)                { VEC1( min(v[i],s) ) };
TVec3 max(TVec3 v,  float s)                { VEC1( max(v[i],s) ) };

TVec3 reflect(TVec3 i, TVec3 n)             { return i-(n*dot(i,n)*2); }
TVec3 refract(TVec3 i, TVec3 n, float ind)  { float w,k; w=-(dot(i,n)*ind); k=1.0+(w-ind)*(w+ind);
                                              return k>-ZERO_TOLERANCE?i*ind+n*(w-sqrt(k)):reflect(i, n); }

TVec3 barycentric(TVec3* v1, TVec3* v2, TVec3* v3, float f, float g)  { return *v1 + (*v2-*v1)*f + (*v3-*v1)*g; };
float dist_point_line(TVec3 v, TVec3 lpos, TVec3 ldir)                { return crs(v-lpos,ldir).lng()/ldir.lng(); };
float projdist_point_line(TVec3 v, TVec3 lpos, TVec3 ldir)            { return dot(v-lpos,ldir); };

#undef VEC1
#undef VEC2
//---------------------------------------------------------------------------

class TMatrix4x4 {
  public:
    float m[16];
    TMatrix4x4&operator = (float s) { forExt(i, 16) m[i]=s; return *this; };
    TMatrix4x4 operator * (TMatrix4x4 mat) { TMatrix4x4 r; r=0; forExt3D(i,j,k,4,4,4) r.m[i*4+j]+=m[k*4+j]*mat.m[i*4+k]; return r; };
    TMatrix4x4&operator *=(TMatrix4x4 mat) { TMatrix4x4 r=*this; *this=0; forExt3D(i,j,k,4,4,4) m[i*4+j]+=r.m[k*4+j]*mat.m[i*4+k]; return *this; };
    TVec3 getAxisX(){ return crt(m[0], m[4], m[8]); };
    TVec3 getAxisY(){ return crt(m[1], m[5], m[9]); };
    TVec3 getAxisZ(){ return crt(m[2], m[6], m[10]); };
    TVec3 getPos()  { return crt(m[3], m[7], m[11]); };
    TVec3 transformCoord(TVec3 v) { TVec3 r=transformNormal(v); forExt(i,3)r[i]+=m[i*4+3]; return r; };
    TVec3 transformNormal(TVec3 v) { TVec3 r; r=0; forExt2D(i,j,3,3)r.v[i]+=v[j]*m[i*4+j]; return r; };
};

TMatrix4x4 matScaling(TVec3 v) { TMatrix4x4 m={v[0],0,0,0,0,v[1],0,0,0,0,v[2],0,0,0,0,1}; return m; };
TMatrix4x4 matScaling(float s) { TMatrix4x4 m={s,0,0,0,0,s,0,0,0,0,s,0,0,0,0,1}; return m; };
TMatrix4x4 matRot(float, TVec3);
TMatrix4x4 matRotX(float a) { TMatrix4x4 m={1,0,0,0,0,cos(a),-sin(a),0,0,sin(a),cos(a),0,0,0,0,1}; return m; };
TMatrix4x4 matRotY(float a) { TMatrix4x4 m={cos(a),0,sin(a),0,0,1,0,0,-sin(a),0,cos(a),0,0,0,0,1}; return m; };
TMatrix4x4 matRotZ(float a) { TMatrix4x4 m={cos(a),-sin(a),0,0,sin(a),cos(a),0,0,0,0,1,0,0,0,0,1}; return m; };
TMatrix4x4 matRotZXY(TVec3 v) { return matRotZ(v[2])*matRotX(v[0])*matRotY(v[1]); };
TMatrix4x4 matIdentity() { TMatrix4x4 m={1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1}; return m; };
TMatrix4x4 matTranslation(TVec3 v) { TMatrix4x4 m={1,0,0,v[0],0,1,0,v[1],0,0,1,v[2],0,0,0,1}; return m; };
TMatrix4x4 transpose(TMatrix4x4 m) { TMatrix4x4 r; forExt2D(i,j,4,4)r.m[i*4+j]=m.m[j*4+i]; return r; };
Dir ist ja sicherlich klar, dass das grauenhaft ist. Bei sowas finde ich etwas mehr Fleiß angebracht. Lieber ein bischen mehr Code tippen, als die komplette Übersicht zu zerstören und eventuelle Wechselwirkungen zu riskieren. Man denke nur an das schöne min/max-Problem von Windows...

Defines sind, wie schon häufig diskutiert, in 99% aller Fälle die falsche Wahl. Schreib lieber mehr Code. Von mir aus pack die for-Schleife in eine Funktion. Da mag zwar Performance-Einbusse bringen, aber die sind es auf jeden Fall wert, wenn du dadurch kryptische defines vermeiden kannst.
Ohne Input kein Output.
Benutzeravatar
Krishty
Establishment
Beiträge: 8316
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [Tipps & Tricks] bad programming

Beitrag von Krishty »

Besser und ohne Wiederholerei mit Templates …

Aber wie heißt es doch so schön? It was hard to write, so it should be hard to read!
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Zudomon
Establishment
Beiträge: 2259
Registriert: 25.03.2009, 07:20
Kontaktdaten:

Re: [Tipps & Tricks] bad programming

Beitrag von Zudomon »

BeRsErKeR hat geschrieben:
Zudomon hat geschrieben:Es ist schade, dass es keine Defines gibt, sonst könnte man da nämlich auch damit abkürzen... in C++ hab ich damit richtig dreckig programmiert...

Erstmal schöne 1D-, 2D- und 3D-Schleifen

Code: Alles auswählen

#define forExt(i, t)              for(int (i)=0; (i)<int(t); (i)++)
#define forExt2D(i,j,t1,t2)       forExt(i, t1) forExt(j, t2)
#define forExt3D(i,j,k,t1,t2,t3)  forExt2D(i,j,t1,t2) forExt(k, t3)
Und dann daraus Vektor und Matrix Klassen bauen:

Code: Alles auswählen

#define VEC1(exp)  TVec3 r; forExt(i, 3) r.v[i]=exp; return r;
#define VEC2(exp)  forExt(i, 3) v[i]exp; return *this;

class TVec3{
  public:
    float v[3];
    TVec3&operator = (float s)   { forExt(i, 3) v[i]=s; return *this; };
    TVec3 operator - ()          { VEC1( -v[i]         ) };
    TVec3 operator - (TVec3 opp) { VEC1( v[i]-opp.v[i] ) };
    TVec3 operator - (float s)   { VEC1( v[i]-s        ) };
    TVec3 operator + (TVec3 opp) { VEC1( v[i]+opp.v[i] ) };
    TVec3 operator + (float s)   { VEC1( v[i]+s        ) };
    TVec3 operator * (float s)   { VEC1( v[i]*s        ) };
    TVec3 operator / (float s)   { DIV0( s, return operator=(0); , return operator*(1.0/s); ) };
    TVec3&operator -=(TVec3 opp) { VEC2( -=opp.v[i]    ) };
    TVec3&operator -=(float s)   { VEC2( -=s           ) };
    TVec3&operator +=(TVec3 opp) { VEC2( +=opp.v[i]    ) };
    TVec3&operator +=(float s)   { VEC2( +=s           ) };
    TVec3&operator *=(float s)   { VEC2( *=s           ) };
    TVec3&operator /=(float s)   { DIV0( s, return *this; , VEC2( /=s; ) ) };
    float&operator [](int index) { return v[index]; };
    float lngSQ()                { return sqr(v[0])+sqr(v[1])+sqr(v[2]); };
    float lng()                  { return sqrt(lngSQ()); };
    void writeTo( char *p )      { *(p++)=_Byte(v[0]); *(p++)=_Byte(v[1]); *p=_Byte(v[2]); } ;
};

TVec3 crt(float a,  float b,  float c)      { TVec3 r={a,b,c}; return r; };
float dot(TVec3 v1, TVec3 v2)               { float r=0; forExt(i,3) r+=v1[i]*v2[i]; return r; };
TVec3 crs(TVec3 v1, TVec3 v2)               { TVec3 r; forExt(i,3) r.v[i]=v1[(i+1)%3]*v2[(i+2)%3]-v1[(i+2)%3]*v2[(i+1)%3]; return r; };
TVec3 nrm(TVec3 v)                          { return v / v.lng(); }
TVec3 lrp(TVec3 v1, TVec3 v2, float s)      { TVec3 r; forExt(i,3)r.v[i]=v1[i]+s*(v2[i]-v1[i]); return r; };
TVec3 normal(TVec3 v1, TVec3 v2, TVec3 v3)  { return crs(v2-v1, v3-v1); }
TVec3 sat(TVec3 v)                          { VEC1( sat(v[i]) ) };

bool same(TVec3*v1, TVec3*v2, float s)      { return (*v1-*v2).lng()<s; };

TVec3 min(TVec3 v1, TVec3 v2)               { VEC1( min(v1[i], v2[i]) ) };
TVec3 max(TVec3 v1, TVec3 v2)               { VEC1( max(v1[i], v2[i]) ) };
TVec3 min(TVec3 v,  float s)                { VEC1( min(v[i],s) ) };
TVec3 max(TVec3 v,  float s)                { VEC1( max(v[i],s) ) };

TVec3 reflect(TVec3 i, TVec3 n)             { return i-(n*dot(i,n)*2); }
TVec3 refract(TVec3 i, TVec3 n, float ind)  { float w,k; w=-(dot(i,n)*ind); k=1.0+(w-ind)*(w+ind);
                                              return k>-ZERO_TOLERANCE?i*ind+n*(w-sqrt(k)):reflect(i, n); }

TVec3 barycentric(TVec3* v1, TVec3* v2, TVec3* v3, float f, float g)  { return *v1 + (*v2-*v1)*f + (*v3-*v1)*g; };
float dist_point_line(TVec3 v, TVec3 lpos, TVec3 ldir)                { return crs(v-lpos,ldir).lng()/ldir.lng(); };
float projdist_point_line(TVec3 v, TVec3 lpos, TVec3 ldir)            { return dot(v-lpos,ldir); };

#undef VEC1
#undef VEC2
//---------------------------------------------------------------------------

class TMatrix4x4 {
  public:
    float m[16];
    TMatrix4x4&operator = (float s) { forExt(i, 16) m[i]=s; return *this; };
    TMatrix4x4 operator * (TMatrix4x4 mat) { TMatrix4x4 r; r=0; forExt3D(i,j,k,4,4,4) r.m[i*4+j]+=m[k*4+j]*mat.m[i*4+k]; return r; };
    TMatrix4x4&operator *=(TMatrix4x4 mat) { TMatrix4x4 r=*this; *this=0; forExt3D(i,j,k,4,4,4) m[i*4+j]+=r.m[k*4+j]*mat.m[i*4+k]; return *this; };
    TVec3 getAxisX(){ return crt(m[0], m[4], m[8]); };
    TVec3 getAxisY(){ return crt(m[1], m[5], m[9]); };
    TVec3 getAxisZ(){ return crt(m[2], m[6], m[10]); };
    TVec3 getPos()  { return crt(m[3], m[7], m[11]); };
    TVec3 transformCoord(TVec3 v) { TVec3 r=transformNormal(v); forExt(i,3)r[i]+=m[i*4+3]; return r; };
    TVec3 transformNormal(TVec3 v) { TVec3 r; r=0; forExt2D(i,j,3,3)r.v[i]+=v[j]*m[i*4+j]; return r; };
};

TMatrix4x4 matScaling(TVec3 v) { TMatrix4x4 m={v[0],0,0,0,0,v[1],0,0,0,0,v[2],0,0,0,0,1}; return m; };
TMatrix4x4 matScaling(float s) { TMatrix4x4 m={s,0,0,0,0,s,0,0,0,0,s,0,0,0,0,1}; return m; };
TMatrix4x4 matRot(float, TVec3);
TMatrix4x4 matRotX(float a) { TMatrix4x4 m={1,0,0,0,0,cos(a),-sin(a),0,0,sin(a),cos(a),0,0,0,0,1}; return m; };
TMatrix4x4 matRotY(float a) { TMatrix4x4 m={cos(a),0,sin(a),0,0,1,0,0,-sin(a),0,cos(a),0,0,0,0,1}; return m; };
TMatrix4x4 matRotZ(float a) { TMatrix4x4 m={cos(a),-sin(a),0,0,sin(a),cos(a),0,0,0,0,1,0,0,0,0,1}; return m; };
TMatrix4x4 matRotZXY(TVec3 v) { return matRotZ(v[2])*matRotX(v[0])*matRotY(v[1]); };
TMatrix4x4 matIdentity() { TMatrix4x4 m={1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1}; return m; };
TMatrix4x4 matTranslation(TVec3 v) { TMatrix4x4 m={1,0,0,v[0],0,1,0,v[1],0,0,1,v[2],0,0,0,1}; return m; };
TMatrix4x4 transpose(TMatrix4x4 m) { TMatrix4x4 r; forExt2D(i,j,4,4)r.m[i*4+j]=m.m[j*4+i]; return r; };
Dir ist ja sicherlich klar, dass das grauenhaft ist. Bei sowas finde ich etwas mehr Fleiß angebracht. Lieber ein bischen mehr Code tippen, als die komplette Übersicht zu zerstören und eventuelle Wechselwirkungen zu riskieren. Man denke nur an das schöne min/max-Problem von Windows...

Defines sind, wie schon häufig diskutiert, in 99% aller Fälle die falsche Wahl. Schreib lieber mehr Code. Von mir aus pack die for-Schleife in eine Funktion. Da mag zwar Performance-Einbusse bringen, aber die sind es auf jeden Fall wert, wenn du dadurch kryptische defines vermeiden kannst.
Naja, könnt ihr sehen wir ihr wollt... zum Beispiel hat mir Marc (zzador hier im Forum) als ich ihm den Post gezeigt habe im ICQ dazu folgendes geschrieben:
(23:21:24) Marc: Die Makros sind schonmal sehr nett
(23:22:19) Marc: Da haste aber extrem gefeilt
(23:24:14) Marc: Das ist hardcore-Democoding code würd ich fast sagen
(23:24:42) Marc: Das ist sogar der Source-Code optimiert :-D:-D:-D
(23:26:36) Marc: Haste die Funktionalität der Klasse mit nem C++ Compiler auch überprüft?
(23:27:44) Marc: Pervers...echt...respekt
(23:28:13) Marc: Wär mir persönlich nie gekommen den Preprozessor so derbe auszunutzen
(23:28:47) Marc: Dadurch wird die ganze Klasse extrem leserlich und kompakt
(23:29:13) Marc: Code-Technisch muss ich das als echtes Meisterwerk sehen
(23:36:26) Zudomon: sorry, war gerade essen
(23:36:51) Zudomon: Die Klassen funktionieren, das war so im Softwareengineering bei uns
(23:37:00) Zudomon: da hatte ich ja den part des raytracers geschrieben
(23:37:27) Zudomon: Danke! Wäre mal geil, wenn da mal in dem Thread jemand verteidigt... :D
(23:37:41) Marc: das mit den Defines?
(23:37:48) Marc: Ist übelst Elite find ich
Er sagt es, die Klassen werden leserlich und kompakt... das ist genau das, was ich brauche... wenn der code tausende Zeilen hat, dann blick ich nicht durch.
zzador
Beiträge: 4
Registriert: 02.09.2011, 21:13

Re: [Tipps & Tricks] bad programming

Beitrag von zzador »

Also ich muss sagen, daß ich die Klasse wirklich gelungen finde. Programmiere C/C++ jetzt schon über 10 Jahre, aber den Preprozessor auf diese Art auszunutzen, auf die Idee bin ich noch nicht gekommen. Netter tipp...durch den Preprozessor wird sich oft widerholender Code eingespart, ohne gleich inline-methoden verwenden zu müssen. Was das Kommentar bzgl. der Templates angeht, wüsste ich jetzt nicht, wo in Zudomon's Beispiel Templates angebracht wären. Zudomon benutzt den Preprozessor um vor dem Kompilieren praktisch per automatischem Copy&Paste seine Code-Fragmente einzufügen. Er benutzt nirgends eine Klassen-Eigenschaft, dessen Daten-Typ erst zur Umsetzungszeit bekannt ist, also ist mir nicht ganz klar, wo sich Templates da als eleganter erweisen sollen. Ich habe solche Vektor-Klassen jetzt schon mehr als einmal geschrieben und kann daher sagen, daß Zudomons Version deutlich kompakter als meine Version ist, aber dennoch nicht weniger leserlich. Ich denke, ich werde in Zukunft den Preprozessor auch etwas intensiver nutzen.
Benutzeravatar
eXile
Establishment
Beiträge: 1136
Registriert: 28.02.2009, 13:27

Re: [Tipps & Tricks] bad programming

Beitrag von eXile »

[youtube]gvdf5n-zI14[/youtube]
Benutzeravatar
Krishty
Establishment
Beiträge: 8316
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [Tipps & Tricks] bad programming

Beitrag von Krishty »

zzador hat geschrieben:Er benutzt nirgends eine Klassen-Eigenschaft, dessen Daten-Typ erst zur Umsetzungszeit bekannt ist, also ist mir nicht ganz klar, wo sich Templates da als eleganter erweisen sollen.
Die gesamte Vektorklasse ist die Realisierung des Konzepts, arithmetische Operatoren zu implementieren, mit einem spezifischen Datentyp. Und dieser Datentyp ist wiederum die Realisierung des Konzepts eines Arrays, auf das jede Operation parallel angewandt wird, mit einem bestimmten Datentyp und einer bestimmten Breite.

Kurz: += und *= durch for_each implementieren (zugegeben – eine Überladung für zwei Arrays wird man brauchen; vielleicht sind aber auch nur meine Lambda-Kenntnisse zu begrenzt), -= und /= als Inverse davon definieren, damit Arithmetic<> instanzieren und der Vektor ist dank zwei Templates fertig.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
dot
Establishment
Beiträge: 1745
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: [Tipps & Tricks] bad programming

Beitrag von dot »

zzador hat geschrieben:Netter tipp...durch den Preprozessor wird sich oft widerholender Code eingespart, ohne gleich inline-methoden verwenden zu müssen.
Ich hoffe doch mal das war Ironie!?
antisteo
Establishment
Beiträge: 928
Registriert: 15.10.2010, 09:26
Wohnort: Dresdem

Re: [Tipps & Tricks] bad programming

Beitrag von antisteo »

dot hat geschrieben:
zzador hat geschrieben:Netter tipp...durch den Preprozessor wird sich oft widerholender Code eingespart, ohne gleich inline-methoden verwenden zu müssen.
Ich hoffe doch mal das war Ironie!?
Also ich finde die Klasse auch ganz nett.
http://fedoraproject.org/ <-- freies Betriebssystem
http://launix.de <-- kompetente Firma
In allen Posts ist das imo und das afaik inbegriffen.
Benutzeravatar
CodingCat
Establishment
Beiträge: 1857
Registriert: 02.03.2009, 21:25
Wohnort: Student @ KIT
Kontaktdaten:

Re: [Tipps & Tricks] bad programming

Beitrag von CodingCat »

antisteo hat geschrieben:
dot hat geschrieben:
zzador hat geschrieben:Netter tipp...durch den Preprozessor wird sich oft widerholender Code eingespart, ohne gleich inline-methoden verwenden zu müssen.
Ich hoffe doch mal das war Ironie!?
Also ich finde die Klasse auch ganz nett.
Ich kann euch auch nur raten, die Finger von solchem Blödsinn zu lassen. Templates und inline-Methoden sind genau dafür da, Code-Generierung einigermaßen verständlich, berechenbar und (Typ-)sicher zu gestalten. Die hier gerade diskutierte Makromagie erfüllt keine dieser Eigenschaften.
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
kaiserludi
Establishment
Beiträge: 467
Registriert: 18.04.2002, 15:31

Re: [Tipps & Tricks] bad programming

Beitrag von kaiserludi »

CodingCat hat geschrieben:
antisteo hat geschrieben:
dot hat geschrieben:
zzador hat geschrieben:Netter tipp...durch den Preprozessor wird sich oft widerholender Code eingespart, ohne gleich inline-methoden verwenden zu müssen.
Ich hoffe doch mal das war Ironie!?
Also ich finde die Klasse auch ganz nett.
Ich kann euch auch nur raten, die Finger von solchem Blödsinn zu lassen. Templates und inline-Methoden sind genau dafür da, Code-Generierung einigermaßen verständlich, berechenbar und (Typ-)sicher zu gestalten. Die hier gerade diskutierte Makromagie erfüllt keine dieser Eigenschaften.
Eben: Durch Inline Methoden wird sich oft widerholender Code eingespart, ohne gleich Makros mitsamt ihrer Nachteile verwenden zu müssen, nicht umgekehrt!
"Mir ist auch klar, dass der Tag, an dem ZFX und Developia zusammengehen werden der selbe Tag sein wird, an dem DirectGL rauskommt."
DirectGL, endlich ist es da
:)

"According to the C++ standard, it's "undefined". That's a technical term that means, in theory, anything can happen: the program can crash, or keep running but generate garbage results, or send Bjarne Stroustrup an e-mail saying how ugly you are and how funny your mother dresses you." :shock:[/size]
zzador
Beiträge: 4
Registriert: 02.09.2011, 21:13

Re: [Tipps & Tricks] bad programming

Beitrag von zzador »

Die gesamte Vektorklasse ist die Realisierung des Konzepts, arithmetische Operatoren zu implementieren, mit einem spezifischen Datentyp. Und dieser Datentyp ist wiederum die Realisierung des Konzepts eines Arrays, auf das jede Operation parallel angewandt wird, mit einem bestimmten Datentyp und einer bestimmten Breite.
Also dadurch hättest Du dann 2 Klassen...Vector<Array> und dein Array, welches die Arithmetischen Operatoren implementiert. 2 Klassen erklären sich wesentlich schwerer von selbst als eine kompakte Klasse wie die von Zudomon.
Ich hoffe doch mal das war Ironie!?
Nein, war es nicht. Ich bin mir auch dadrüber im Klaren, was Inline-Methoden sind, da ich sie ebenfalls sehr oft benutze. Sie sind nichts anderes als Preprozessor-Makros auf Code-Ebene. Im Gegensatz zu Makros müssen sie allerdings in der Klasse definiert, oder zumindest deklariert werden und würden hier in dem Fall von Zudomon die Kompaktheit seiner Klasse negativ beeinträchtigen, oder um es anders zu formulieren: Sie würden ablenken

Und genau das ist der Knackpunkt. Es ging mir von vorne rein um die extreme lesbarkeit von Zudomon's Klasse. Ihre gesamte Funktionalität erklärt sich praktisch von selbst beim betrachten der Klasse, ohne die Dokumentation oder Kommentare zu Rate ziehen zu müssen. Was ich damit sagen will ist, dass man die Funktionalität des Preprozessors ruhig ausnutzen soll, wenn es die Lesbarkeit steigert.
kaiserludi
Establishment
Beiträge: 467
Registriert: 18.04.2002, 15:31

Re: [Tipps & Tricks] bad programming

Beitrag von kaiserludi »

zzador hat geschrieben:
Die gesamte Vektorklasse ist die Realisierung des Konzepts, arithmetische Operatoren zu implementieren, mit einem spezifischen Datentyp. Und dieser Datentyp ist wiederum die Realisierung des Konzepts eines Arrays, auf das jede Operation parallel angewandt wird, mit einem bestimmten Datentyp und einer bestimmten Breite.
Also dadurch hättest Du dann 2 Klassen...Vector<Array> und dein Array, welches die Arithmetischen Operatoren implementiert. 2 Klassen erklären sich wesentlich schwerer von selbst als eine kompakte Klasse wie die von Zudomon.
Ich hoffe doch mal das war Ironie!?
Nein, war es nicht. Ich bin mir auch dadrüber im Klaren, was Inline-Methoden sind, da ich sie ebenfalls sehr oft benutze. Sie sind nichts anderes als Preprozessor-Makros auf Code-Ebene. Im Gegensatz zu Makros müssen sie allerdings in der Klasse definiert, oder zumindest deklariert werden und würden hier in dem Fall von Zudomon die Kompaktheit seiner Klasse negativ beeinträchtigen, oder um es anders zu formulieren: Sie würden ablenken

Und genau das ist der Knackpunkt. Es ging mir von vorne rein um die extreme lesbarkeit von Zudomon's Klasse. Ihre gesamte Funktionalität erklärt sich praktisch von selbst beim betrachten der Klasse, ohne die Dokumentation oder Kommentare zu Rate ziehen zu müssen. Was ich damit sagen will ist, dass man die Funktionalität des Preprozessors ruhig ausnutzen soll, wenn es die Lesbarkeit steigert.
1.
Nein, ein Vector<Array> wäre ja ein Vektor mit lauter Elementen vom Typ Array, Krishty meint aber einen Vektor, der mit Hilfe eines Arrays implementiert wurde. Der Array ist ein Implementierungsdetail, der den Nutzer der Vektorklasse normalerweise gar nicht interessiert.

2.
Nein, offensichtlich bist du dir nicht darüber im Klaren, was inline-Methoden sind oder was Makros sind.
Versuch mal Includeguards wie

Code: Alles auswählen

#ifndef FOO_H
#define FOO_H

// headercode

#endif
mit einer Inlinemethode umzusetzen

oder Checks auf Compilerdefines wie

Code: Alles auswählen

	#ifdef __cplusplus
		extern "C"
		{
	#endif

		// imagine some function declarations here

	#ifdef __cplusplus
		}
	#endif
Das sollte offensichtlich machen, dass Inlinemethoden eben nicht einfach Präprozessormakros auf Compilerebene sind.

Wer schon mal ein 100 Zeilen-Makro debugen durfte, weiß, wie gut der Debugger damit klar kommt, da durch zu steppen.
Und sowas wie

Code: Alles auswählen

#define sum(a, b) a+b
result = sum(5, 5)*5; // looks like result is (5+5)*5==50, but due to the missing "()" in the macro it is 5+5*5==30
kann einem mit inline-methods nicht passieren (die in der Praxis vorkommenden Fälle solcher Bugs sind meist weit weniger offensichtlich zu finden, als es in diesem simplen Beispiel der Fall ist)
"Mir ist auch klar, dass der Tag, an dem ZFX und Developia zusammengehen werden der selbe Tag sein wird, an dem DirectGL rauskommt."
DirectGL, endlich ist es da
:)

"According to the C++ standard, it's "undefined". That's a technical term that means, in theory, anything can happen: the program can crash, or keep running but generate garbage results, or send Bjarne Stroustrup an e-mail saying how ugly you are and how funny your mother dresses you." :shock:[/size]
Benutzeravatar
dot
Establishment
Beiträge: 1745
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: [Tipps & Tricks] bad programming

Beitrag von dot »

Wer immer Makros für eine tolle Idee hält, den bitte ich, folgenden Code zu kompilieren:

Code: Alles auswählen

#include <windows.h>
#include <iostream>
#include <algorithm>

int main()
{
  int a, b;
  std::cin >> a >> b;
  std::cou << "max(a, b) = " << std::max(a, b);
}
kaiserludi
Establishment
Beiträge: 467
Registriert: 18.04.2002, 15:31

Re: [Tipps & Tricks] bad programming

Beitrag von kaiserludi »

dot hat geschrieben:Wer immer Makros für eine tolle Idee hält, den bitte ich, folgenden Code zu kompilieren:

Code: Alles auswählen

#include <windows.h>
#include <iostream>
#include <algorithm>

int main()
{
  int a, b;
  std::cin >> a >> b;
  std::cou << "max(a, b) = " << std::max(a, b);
}
Wenn, dann so:

Code: Alles auswählen

#include <windows.h>
#include <iostream>
#include <algorithm>

int main()
{
  int a, b;
  std::cin >> a >> b;
  std::cout << "max(a, b) = " << max(a, b);
}
Dann kompiliert das auch.
Was du uns mit dem Code nun sagen willst, ist mir aber nicht klar. Der Code macht doch genau das, was er soll?
"Mir ist auch klar, dass der Tag, an dem ZFX und Developia zusammengehen werden der selbe Tag sein wird, an dem DirectGL rauskommt."
DirectGL, endlich ist es da
:)

"According to the C++ standard, it's "undefined". That's a technical term that means, in theory, anything can happen: the program can crash, or keep running but generate garbage results, or send Bjarne Stroustrup an e-mail saying how ugly you are and how funny your mother dresses you." :shock:[/size]
Benutzeravatar
dot
Establishment
Beiträge: 1745
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: [Tipps & Tricks] bad programming

Beitrag von dot »

Nicht wenn das std:: dort steht und eben genau das ist der Punkt, denn eigentlich sollte es kompilieren. Nun ist die Frage warum es das nicht tut...
kaiserludi
Establishment
Beiträge: 467
Registriert: 18.04.2002, 15:31

Re: [Tipps & Tricks] bad programming

Beitrag von kaiserludi »

dot hat geschrieben:Nicht wenn das std:: dort steht und eben genau das ist der Punkt, denn eigentlich sollte es kompilieren. Nun ist die Frage warum es das nicht tut...
Dort steht nirgends, dass max laut Standard zum namespace stl gehört, nur dass es zu den stl-Algorithmen gehört, was nicht ausschließt, dass es im globalen Namespace liegen kann.
"Mir ist auch klar, dass der Tag, an dem ZFX und Developia zusammengehen werden der selbe Tag sein wird, an dem DirectGL rauskommt."
DirectGL, endlich ist es da
:)

"According to the C++ standard, it's "undefined". That's a technical term that means, in theory, anything can happen: the program can crash, or keep running but generate garbage results, or send Bjarne Stroustrup an e-mail saying how ugly you are and how funny your mother dresses you." :shock:[/size]
Benutzeravatar
CodingCat
Establishment
Beiträge: 1857
Registriert: 02.03.2009, 21:25
Wohnort: Student @ KIT
Kontaktdaten:

Re: [Tipps & Tricks] bad programming

Beitrag von CodingCat »

Ich kenn noch einen, ich kenn noch einen! *hüpf, hüpf*

Code: Alles auswählen

#include <windows.h>
#include <iostream>

int main()
{
  int near, far;
  std::cin >> near >> far;
  std::cout << "near = " << near << "; far = " << far;
}
OK, ganz leicht am Thema Geltungsbereiche vorbei ... :P


kaiserludi: Der Punkt ist, du kannst ohne #undef den STL-Algorithmus max() nicht mehr nutzen, selbst wenn du wolltest. ;-)
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
Benutzeravatar
dot
Establishment
Beiträge: 1745
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: [Tipps & Tricks] bad programming

Beitrag von dot »

kaiserludi hat geschrieben:Dort steht nirgends, dass max laut Standard zum namespace stl gehört, nur dass es zu den stl-Algorithmen gehört, was nicht ausschließt, dass es im globalen Namespace liegen kann.
Natürlich liegt max() im namespace std. Das steht nicht explizit dort weil es sich von selbst versteht. Aber bitteschön:
ISO/IEC 14882:2011 §25.1 hat geschrieben:

Code: Alles auswählen

namespace std {
  ...
  template<class T> const T& max(const T& a, const T& b);
  ...
}
CodingCat hat geschrieben:kaiserludi: Der Punkt ist, du kannst ohne #undef den STL-Algorithmus max() nicht mehr nutzen, selbst wenn du wolltest. ;-)
Na toll, jetzt hast dus gespoiled :P
Denn vor allem muss man überhaupt erstmal draufkommen was der Fehler ist. Die Meldungen die man da bekommt, sind normalerweise alles andre als hilfreich.
Man muss nurmal googlen wieviele Leute ständig in irgendwelchen Foren völlig verzweifelt um Hilfe rufen, weil sie am Ende ihrer Kräfte sind und einfach absolut nicht draufkommen, woher diese komische Linkerfehler kommen, sobald sie die GetMessage() Methode ihrer neuen, supertollen, lockfree MessageQueue Klasse aufrufen wollen. Es macht einfach keinen Sinn, der Code sieht völlig korrekt aus und vor allem: Warum sucht der Linker nach einer ?GetMessageW@MessageQueue@mystuff@@QAEXXZ!? :shock: Tja, Makros bei der Arbeit ;)
Und die Moral von der Geschicht': Makros verwend' man nicht. Außer für bedingte Kompilierung und andere Dinge, wo Makros eben gebraucht werden. Auf gar keinen Fall jedoch, anstatt einer Funktion.
kaiserludi
Establishment
Beiträge: 467
Registriert: 18.04.2002, 15:31

Re: [Tipps & Tricks] bad programming

Beitrag von kaiserludi »

Jetzt würde mich aber interessieren, warum er das max im std-namespace nicht findet, wenn es ein globales max-define gibt?
Gehe ich korrekt in der Annahme, dass der Präprozessor als reiner Textersetzer aus std::max(a, b) dann std::((a<b)?b:a) macht, was der Compiler dann natürlich nicht versteht?
"Mir ist auch klar, dass der Tag, an dem ZFX und Developia zusammengehen werden der selbe Tag sein wird, an dem DirectGL rauskommt."
DirectGL, endlich ist es da
:)

"According to the C++ standard, it's "undefined". That's a technical term that means, in theory, anything can happen: the program can crash, or keep running but generate garbage results, or send Bjarne Stroustrup an e-mail saying how ugly you are and how funny your mother dresses you." :shock:[/size]
Benutzeravatar
dot
Establishment
Beiträge: 1745
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: [Tipps & Tricks] bad programming

Beitrag von dot »

kaiserludi hat geschrieben:Gehe ich korrekt in der Annahme, dass der Präprozessor als reiner Textersetzer aus std::max(a, b) dann std::((a<b)?b:a) macht, was der Compiler dann natürlich nicht versteht?
Exakt. Und der Programmierer versteht die daraus resultierenden Fehlermeldungen in der Regel noch weniger...
kaiserludi
Establishment
Beiträge: 467
Registriert: 18.04.2002, 15:31

Re: [Tipps & Tricks] bad programming

Beitrag von kaiserludi »

dot hat geschrieben:
kaiserludi hat geschrieben:Gehe ich korrekt in der Annahme, dass der Präprozessor als reiner Textersetzer aus std::max(a, b) dann std::((a<b)?b:a) macht, was der Compiler dann natürlich nicht versteht?
Exakt. Und der Programmierer versteht die daraus resultierenden Fehlermeldungen in der Regel noch weniger...
Was lernen wir daraus: MAKROS immer in ALL_UPPERCASE, wenn sie unbedingt sein müssen, alles andere eben nicht in in der Weise deklarieren, dann ist das Risiko solcher Fehlerquellen schon einmal massiv gesenkt.
Ändert natürlich nichts daran, dass eine globale inline-Funktion max() das Problem nicht produziert hätte.
"Mir ist auch klar, dass der Tag, an dem ZFX und Developia zusammengehen werden der selbe Tag sein wird, an dem DirectGL rauskommt."
DirectGL, endlich ist es da
:)

"According to the C++ standard, it's "undefined". That's a technical term that means, in theory, anything can happen: the program can crash, or keep running but generate garbage results, or send Bjarne Stroustrup an e-mail saying how ugly you are and how funny your mother dresses you." :shock:[/size]
Antworten