[c++] Tekenen met geneste for loops

Pagina: 1
Acties:
  • 512 views sinds 30-01-2008
  • Reageer

Acties:
  • 0 Henk 'm!

  • twit
  • Registratie: September 2002
  • Laatst online: 09:17
Ik ben bezig met het leren van c++ volgens , hier op GoT vast wel bekend, "Aan de slag met c++ ". Ik ben nu bij een aantal opdrachten van dat boek aangekomen waarin ze je inzicht willen testen en willlen laten zien wat de mogelijkheden van for loops zijn.

Dit moet je doen door verschillende figuren te tekenen waarbij je gebruik maakt van hele basic c++ dingen: cout, manipulators van cout , for loops.

Ik heb het onderstaande figuur al gemaakt :
code:
1
2
3
4
5
6
*
**
***
****
*****
******

Dat heb ik gedaan met de volgende code :
C++:
1
2
3
4
5
6
7
for(int kolom=1;kolom<=7;kolom++){
    for(int rij=1;rij<=counter;rij++){
      cout  << "*" ;
      }
    counter++;
    cout << endl;
  }


Dat was op zich na heel lang puzzelen nog wel te doen maar nu moet ik bijv een gespiegelde versie van de figuur van hierboven hebben of een piramide. En dat is dus eigenlijk mijn vraag. Hoe kan ik nu bijv 2 van deze dingen tegen elkaar laten zien of ze spiegelen e.d

Gewenst is dus :
code:
1
2
3
4
        *
      **
    ***
  ****

En een piramide.

[ Voor 8% gewijzigd door twit op 11-04-2003 13:28 ]

gutta cavat lapidem non vi, sed saepe cadendo. Sic homo fit doctus, non vi, sed saepe legendo


Acties:
  • 0 Henk 'm!

  • PiepPiep
  • Registratie: Maart 2002
  • Laatst online: 18-01-2023
Als je de binnenste for nou eens copy paste, en dan nog een keer copy paste.
De eerste laat je spatie " " afdrukken, de 2e en 3e laat je "*" afdrukken.
Dan heb je denk ik al best een mooie piramide.
Wat je daarna ook kan doen is de 2e en 3e samenvoegen, deze zijn immers hetzelfde, dit kan door "*" te vervangen voor "**"

486DX2-50 16MB ECC RAM 4x 500MB Drive array 1.44MB FDD MS-Dos 6.22


Acties:
  • 0 Henk 'm!

  • darthdrinker
  • Registratie: November 1999
  • Laatst online: 24-07 10:25

darthdrinker

HELP!

Als je dat net zo wilt doen als de eerste keer dan zal je daar nieuwe code voor moeten schrijven. Dat wil niet zeggen dat je de code die je al had geschreven weg kan gooien.
Als ik niet goed antwoord geef op je vraag moet je misschien nog even wat duidelijker uitleggen wat je bedoelt.

Iemand doodmaken met een blije mus.....


Acties:
  • 0 Henk 'm!

  • twit
  • Registratie: September 2002
  • Laatst online: 09:17
darthdrinker schreef op 11 april 2003 @ 13:30:
Als je dat net zo wilt doen als de eerste keer dan zal je daar nieuwe code voor moeten schrijven. Dat wil niet zeggen dat je de code die je al had geschreven weg kan gooien.
Als ik niet goed antwoord geef op je vraag moet je misschien nog even wat duidelijker uitleggen wat je bedoelt.
Ik wil dus niets meer dan de driehoek die je nu ziet staan maar dan in spiegelbeeld zoals ik na mijn edit onderaan heb proberen duidelijk te maken. Ik weet dat het iets in de richting van counter =7. en dan counter -- ipv ++ moet zijn maar ik zie het gewoon niet .

@pieppiep: Ja idd die piramide moet op jou manier wel lukken als ik eenmaal door heb hoe ik die andere spiegel. Dat is gewoon die 2 tegenmekaar aan zetten.

[ Voor 11% gewijzigd door twit op 11-04-2003 13:36 ]

gutta cavat lapidem non vi, sed saepe cadendo. Sic homo fit doctus, non vi, sed saepe legendo


Acties:
  • 0 Henk 'm!

  • AaroN
  • Registratie: Februari 2001
  • Laatst online: 16-08-2023

AaroN

JayGTeam (213177)

aftellen bijvoorbeeld geeft een omgekeerde versie:
C++:
1
2
3
4
5
6
for(int kolom=7;kolom;kolom--){
     for(int rij=0;rij<kolom;rij++){
          cout << "*";
     }
     cout << endl;
}

en als je een piramide wilt hebben moet het nog iets anders icm een hulp variabele:
C++:
1
2
3
4
5
6
7
8
9
    int hulp = 1;
    for(kolom=1;kolom;kolom+=hulp){
        for(int rij=0;rij<kolom;rij++){
            cout << "*";
        }
    if(kolom==7)
        hulp = -1;
    cout << endl;
    }

ik heb bij beide for loops als predicaat alleen kolom staan, dit komt omdat alle waarden behalve 0 TRUE geven, dus dat is een kortere manier van (kolom == 0)

JayGTeam (213177)


Acties:
  • 0 Henk 'm!

  • twit
  • Registratie: September 2002
  • Laatst online: 09:17
AaroN schreef op 11 april 2003 @ 13:39:
aftellen bijvoorbeeld geeft een omgekeerde versie:
C++:
1
2
3
4
5
6
for(int kolom=7;kolom;kolom--){
     for(int rij=0;rij<kolom;rij++){
          cout << "*";
     }
     cout << endl;
}

en als je een piramide wilt hebben moet het nog iets anders icm een hulp variabele:
C++:
1
2
3
4
5
6
7
8
9
    int hulp = 1;
    for(kolom=1;kolom;kolom+=hulp){
        for(int rij=0;rij<kolom;rij++){
            cout << "*";
        }
    if(kolom==7)
        hulp = -1;
    cout << endl;
    }

ik heb bij beide for loops als predicaat alleen kolom staan, dit komt omdat alle waarden behalve 0 TRUE geven, dus dat is een kortere manier van (kolom == 0)
TNX, zo simpel is het dus .... ik wist wel dat het niet moeilijker kon zijn want het was echt vooraan in het boek.

EDIT: te voorbarig, dit had ik ook al maar nu is tie dus nog op zijn kop. Hij moet dun beginne en naar breed uitlopen. Eens kijekn of ik die laatste stap zelf kan zetten.

[ Voor 14% gewijzigd door twit op 11-04-2003 13:46 ]

gutta cavat lapidem non vi, sed saepe cadendo. Sic homo fit doctus, non vi, sed saepe legendo


Acties:
  • 0 Henk 'm!

  • LAN
  • Registratie: Oktober 2000
  • Niet online

LAN

Als je hem wilt spiegelen (horizontaal) zul je eerst wat spaties neer moeten zetten.
Eerst 6 spaties, en dan 1 sterretje.
Vervolgens telkens 1 spatie minder neerzetten, maar wel telkens een extra sterretje.

Hoe je dit in code doet mag je zelf uitzoeken.
Probeer het eerst eens op papier uit te werken, zodat je begrijpt hoe het figuur wordt opgebouwd.

Je wilt em toch zo?

code:
1
2
3
4
5
6
     *
    **
   ***
  ****
 *****
******

[ Voor 12% gewijzigd door LAN op 11-04-2003 13:46 ]


Acties:
  • 0 Henk 'm!

  • darthdrinker
  • Registratie: November 1999
  • Laatst online: 24-07 10:25

darthdrinker

HELP!

twit schreef op 11 April 2003 @ 13:33:
[...]


Ik wil dus niets meer dan de driehoek die je nu ziet staan maar dan in spiegelbeeld zoals ik na mijn edit onderaan heb proberen duidelijk te maken. Ik weet dat het iets in de richting van counter =7. en dan counter -- ipv ++ moet zijn maar ik zie het gewoon niet .
je kan bijvoorbeeld met een extra for lus spaties zetten voordat je de * op et scherm zet.

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
  for(int kolom=1;kolom<=7;kolom++)
  {
    for(int extra=6; extra>counter2; extra-- )
    {
      cout << " ";
    }
    for(int rij=1;rij<=counter;rij++)
    { 
      cout  << "*" ; 
    } 
    counter2 += 2;
    counter++; 
    cout << endl; 
  }

Iemand doodmaken met een blije mus.....


Acties:
  • 0 Henk 'm!

  • twit
  • Registratie: September 2002
  • Laatst online: 09:17
Waarom kan dat eigenljik niet gewoon met de Cout manipulator, SETW, die doet (ljkt mij dan ) precies wat ik zoek.

volgens mij (ik denk dat ik hem heb ) moet het kunnen met cout << setw(iets-iets) <<"* " zodat er steeds spatie minder komt.

gutta cavat lapidem non vi, sed saepe cadendo. Sic homo fit doctus, non vi, sed saepe legendo


Acties:
  • 0 Henk 'm!

  • LAN
  • Registratie: Oktober 2000
  • Niet online

LAN

Volgens mij zul je dan ook setiosflags(ios::right) moeten gebruiken (rechts uitlijnen).

edit:

Pardon, toch niet.

[ Voor 19% gewijzigd door LAN op 11-04-2003 13:53 ]


Acties:
  • 0 Henk 'm!

  • twit
  • Registratie: September 2002
  • Laatst online: 09:17
LAN schreef op 11 april 2003 @ 13:45:
Als je hem wilt spiegelen (horizontaal) zul je eerst wat spaties neer moeten zetten.
Eerst 6 spaties, en dan 1 sterretje.
Vervolgens telkens 1 spatie minder neerzetten, maar wel telkens een extra sterretje.

Hoe je dit in code doet mag je zelf uitzoeken.
Probeer het eerst eens op papier uit te werken, zodat je begrijpt hoe het figuur wordt opgebouwd.

Je wilt em toch zo?

code:
1
2
3
4
5
6
     *
    **
   ***
  ****
 *****
******
DAT is hoe ik hem wil idd. TNX.

gutta cavat lapidem non vi, sed saepe cadendo. Sic homo fit doctus, non vi, sed saepe legendo


Acties:
  • 0 Henk 'm!

  • AaroN
  • Registratie: Februari 2001
  • Laatst online: 16-08-2023

AaroN

JayGTeam (213177)

setw() werkt als volgt :
C++:
1
cout << setw(3) << setfill(' ') << '*';

geeft <spatie><spatie>*

JayGTeam (213177)


Acties:
  • 0 Henk 'm!

  • twit
  • Registratie: September 2002
  • Laatst online: 09:17
Dat weet ik dus aaron daarom zei kik van het moet daarmee kunnen dat bespaart je speciale loop voor de spaties. IK moet dus een of anderer variabele maken die telkens 1 kleine word en dan setw(variabele) doen .

gutta cavat lapidem non vi, sed saepe cadendo. Sic homo fit doctus, non vi, sed saepe legendo


Acties:
  • 0 Henk 'm!

  • AaroN
  • Registratie: Februari 2001
  • Laatst online: 16-08-2023

AaroN

JayGTeam (213177)

C++:
1
2
3
4
5
6
7
8
9
10
11
12
    for(kolom=1;kolom<=7;kolom++){ 
        cout  <<setw((7-counter)) <<setfill(' ');
        for(int rij=1;rij<=counter;rij++){ 
            cout << "*" ; 
        }
        for(rij=1;rij<=counter;rij++){ 
            cout << "*" ; 
        }
        counter++; 
        cout << endl; 
    }
    

voílá!

code:
1
2
3
4
5
6
     **
    ****
   ******
  ********
 **********
************

btw: ik las die post meer als een vraag, dus ik geef een voorbeeldje :)

[ Voor 75% gewijzigd door AaroN op 11-04-2003 14:48 ]

JayGTeam (213177)


Acties:
  • 0 Henk 'm!

  • Thijsch
  • Registratie: Februari 2002
  • Nu online
Ik heb hem zo:

C:
1
2
3
4
5
6
7
8
9
10
11
  for (i = 0; i < 9; i++)
    {
      for(a = 0; a < ( 9 -i ); a++)
    printf(" ");
    
      for(a = a; a <9; a++)
    printf("*");
      
      printf("\n");

    }


Dit is dan c, maar het is een kwestie van printf vervangen voor cout :)

hij ziet er btw zo uit:

code:
1
2
3
4
5
6
7
8
        *
       **
      ***
     ****
    *****
   ******
  *******
 ********

[ Voor 39% gewijzigd door Thijsch op 11-04-2003 19:22 ]


Acties:
  • 0 Henk 'm!

  • twit
  • Registratie: September 2002
  • Laatst online: 09:17
ParaDot schreef op 11 April 2003 @ 19:18:
Ik heb hem zo:

C:
1
2
3
4
5
6
7
8
9
10
11
  for (i = 0; i < 9; i++)
    {
      for(a = 0; a < ( 9 -i ); a++)
    printf(" ");
    
      for(a = a; a <9; a++)
    printf("*");
      
      printf("\n");

    }


Dit is dan c, maar het is een kwestie van printf vervangen voor cout :)

hij ziet er btw zo uit:

code:
1
2
3
4
5
6
7
8
        *
       **
      ***
     ****
    *****
   ******
  *******
 ********

gutta cavat lapidem non vi, sed saepe cadendo. Sic homo fit doctus, non vi, sed saepe legendo


Acties:
  • 0 Henk 'm!

  • twit
  • Registratie: September 2002
  • Laatst online: 09:17
ParaDot schreef op 11 April 2003 @ 19:18:
Ik heb hem zo:

C:
1
2
3
4
5
6
7
8
9
10
11
  for (i = 0; i < 9; i++)
    {
      for(a = 0; a < ( 9 -i ); a++)
    printf(" ");
    
      for(a = a; a <9; a++)
    printf("*");
      
      printf("\n");

    }


Dit is dan c, maar het is een kwestie van printf vervangen voor cout :)

hij ziet er btw zo uit:

code:
1
2
3
4
5
6
7
8
        *
       **
      ***
     ****
    *****
   ******
  *******
 ********
Dat was idd de oplossing. een extra loop voor de spaties.

gutta cavat lapidem non vi, sed saepe cadendo. Sic homo fit doctus, non vi, sed saepe legendo


Acties:
  • 0 Henk 'm!

  • LAN
  • Registratie: Oktober 2000
  • Niet online

LAN

Ik kan het niet laten om ook nog een oplossing te posten.

C++:
1
2
3
4
5
6
7
8
9
10
11
int spaces=7;
int stars=1;

for(int i=0;i<=6;i++)       // loop voor aantal rijen
{
   cout << setw(spaces--);  // begin met sterretjes op de plaats van setw()
   for(int j=0;j<stars;j++) // loop om sterretjes te plaatsen
      cout << "*";          // aantal afhankelijk van variabele stars
   cout << endl;            // even een entertje aan het einde
   stars++;                 // verhoog met 1, zodat je een driehoek krijgt
}


En als je dan een piramide wilt doe je stars+=2; ipv stars++;

Acties:
  • 0 Henk 'm!

  • twit
  • Registratie: September 2002
  • Laatst online: 09:17
LAN schreef op 11 april 2003 @ 21:03:
Ik kan het niet laten om ook nog een oplossing te posten.

C++:
1
2
3
4
5
6
7
8
9
10
11
int spaces=7;
int stars=1;

for(int i=0;i<=6;i++)       // loop voor aantal rijen
{
   cout << setw(spaces--);  // begin met sterretjes op de plaats van setw()
   for(int j=0;j<stars;j++) // loop om sterretjes te plaatsen
      cout << "*";          // aantal afhankelijk van variabele stars
   cout << endl;            // even een entertje aan het einde
   stars++;                 // verhoog met 1, zodat je een driehoek krijgt
}


En als je dan een piramide wilt doe je stars+=2; ipv stars++;
Ik denk dat dit nog het meest in de buurt komt van de oplossing die ze in het boek bedoelden aangezien het een opdracht is die heel erg vooraan in het boek stond. IK heb alleen het idee dat je nu een oneindige loop maakt doordat J<stars en stars ++ ?

gutta cavat lapidem non vi, sed saepe cadendo. Sic homo fit doctus, non vi, sed saepe legendo


Acties:
  • 0 Henk 'm!

  • PiepPiep
  • Registratie: Maart 2002
  • Laatst online: 18-01-2023
twit schreef op 11 april 2003 @ 21:42:
[...]


Ik denk dat dit nog het meest in de buurt komt van de oplossing die ze in het boek bedoelden aangezien het een opdracht is die heel erg vooraan in het boek stond. IK heb alleen het idee dat je nu een oneindige loop maakt doordat J<stars en stars ++ ?
De start++ staat niet in de for loop van j<start

486DX2-50 16MB ECC RAM 4x 500MB Drive array 1.44MB FDD MS-Dos 6.22


Acties:
  • 0 Henk 'm!

  • twit
  • Registratie: September 2002
  • Laatst online: 09:17
Om het even compleet te maken zal ik hierbij de code posten van de uiteindelijke opdracht waar ik dus naartoe gewerkt heb.

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
for(int rij=0;rij<9;rij++){
    cout << setw(9-rij);
    for(int kolom=0;kolom<=counter;kolom++){
      cout << "*";
    }
  counter+=2;
  cout << endl;
  ;
  }
  
  for(int rij=0;rij<10;rij++){
    cout << setw(1+rij);
    for(int kolom=0;kolom<=counter2;kolom++){
      cout << "*";
    }


En dit heeft de volgende uitvoer:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
        *
       ***
      *****
     *******
    *********
   ***********
  *************
 ***************
*****************
*****************
 ***************
  *************
   ***********
    *********
     *******
      *****
       ***
        *

gutta cavat lapidem non vi, sed saepe cadendo. Sic homo fit doctus, non vi, sed saepe legendo


Acties:
  • 0 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 19:25
Een pyramide is echt makkelijk!
C++:
1
2
3
4
5
6
7
8
for(int n = 0; n < 1; ++n)
{
    std::cout << "    *"     << endl <<
              << "   ***"    << endl <<
              << "  *****"   << endl <<
              << " *******"  << endl <<
              << "*********" << endl;
}

:P

Op een wat serieuzere (en ingewikkeldere) toon: zou het mogelijk zijn om de C++ compiler dit soort lusjes te laten unrollen? Ik kan me voorstellen dat je met recursieve templates een heel eind kan komen. Eens even knutselen.

[ Voor 67% gewijzigd door Soultaker op 14-04-2003 12:42 . Reden: endl's toegevoegd ]


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 20:29

.oisyn

Moderator Devschuur®

Demotivational Speaker

Soultaker: je vergeet wat endl's ;)

Maar zo'n template is idd wel leuk :P Mijn suggestie:

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
template <int rows, int spaces> inline void drawPyramid (std::ostream & os)
{
    drawPyramid<rows - 1, spaces + 1> (os);
    os << std::string (spaces, ' ')
       << std::string (rows * 2 - 1, '*')
       << std::endl;
}

template <int spaces> inline void drawPyramid<0, spaces> (std::ostream & os)
{
}

int main ()
{
    drawPyramid<5, 0> (std::cout);
    return 0;
}


ondersteuning voor partial template specialization is wel nodig (vziw geen probleem met g++ 3.*, msvc++ 7.1 (vs.net 2003) en comeau) :)

uit het blote hoofd overigens, dus niet getest

.edit: dit compilet niet met comeau, hij valt op een of andere manier over die partial specialization... weet iemand waarom? Ik kan er niets over vinden in de standaard.
.edit2: gcc doet ook moeilijk... msvc++ 7.1 kan ik momenteel even niet testen

Blijkbaar zien ze het niet als partial specialization maar gewoon als nieuwe template definition, omdat er template argumenten zijn... vandaar dat ze de < achter de functie-naam niet begrijpen

Ik kan 'm wel omtoveren naar structs of classes, maar het blijft toch wazig
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
template <int rows, int spaces> struct PyramidDrawer
{
    inline static void draw (std::ostream & os)
    {
        PyramidDrawer<rows - 1, spaces + 1>::draw (os);
        os << std::string (spaces, ' ')
           << std::string (rows * 2 - 1, '*')
           << std::endl;
    }
};

template <int spaces> struct PyramidDrawer<0, spaces>
{
    inline static void draw (std::ostream & os) { }
};

template <int rows> inline void drawPyramid (std::ostream & os)
{
    PyramidDrawer<rows, 0>::draw ();
}

int main ()
{
    drawPyramid<5> (std::cout);
    return 0;
}


deze is overigens wel wat mooier omdat je als gebruiker nu die 0 niet als extra parameter mee hoeft te geven, maar dat is met de functie-methode van hierboven ook wel mogelijk

[ Voor 78% gewijzigd door .oisyn op 14-04-2003 12:09 . Reden: layout verneuking fixed ]

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!

  • Rataplan
  • Registratie: Oktober 2001
  • Niet online

Rataplan

per aspera ad astra

Tjee, wat een lappen allemaal :)
C++:
1
2
3
4
5
6
for (int a=1;a<=9;a++) 
{ 
    for (int b=9;b>0;b--) 
        printf((a<b)?" ":"*"); 
    printf("\n"); 
}
Piramide (met math.h):
C++:
1
2
3
4
5
6
for (int a=1;a<=9;a++) 
{ 
    for (int b=-9;b<=9;b++) 
        printf((abs(b)<a)?"*":" "); 
    printf("\n"); 
}


Iemand nog korter :? :)

[ Voor 17% gewijzigd door Rataplan op 14-04-2003 11:44 . Reden: ...twee karakters korter :D ]


Journalism is printing what someone else does not want printed; everything else is public relations.


Acties:
  • 0 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 19:25
.oisyn schreef op 14 April 2003 @ 10:26:
Soultaker: je vergeet wat endl's ;)
Nu je 't zegt!
Maar zo'n template is idd wel leuk :P Mijn suggestie:

C++:
1
<knip>

.edit: dit compilet niet met comeau, hij valt op een of andere manier over die partial specialization... weet iemand waarom? Ik kan er niets over vinden in de standaard.

.edit2: gcc doet ook moeilijk... msvc++ 7.1 kan ik momenteel even niet testen
Mja, ik ben hier wel vaker tegenop gelopen. Op de een of andere manier kun je functie-templates niet specialiseren ofzo. Ik werk er altijd omheen door een mooie struct te definieren met een bepaalde methode, en die dan te specialiseren.

Wat ik trouwens eigenlijk wilde (maar dat wordt wat lastig is, denk ik) is dat de templates een serie van stringconcatenaties opleveren. De compiler is dan vast wel zo slim om die bij het compileren weg te optimaliseren, zodat je at-runtime alleen nog maar een statische string met je pyramide overhoudt.

Acties:
  • 0 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 19:25
Rataplan schreef op 14 April 2003 @ 11:20:
Tjee, wat een lappen allemaal :)
C++:
1
2
3
4
5
6
for (int a=1;a<=9;a++) 
{ 
    for (int b=9;b>0;b--) 
        printf((a<b)?" ":"*"); 
    printf("\n"); 
}
Piramide (met math.h):
C++:
1
2
3
4
5
6
for (int a=1;a<=9;a++) 
{ 
    for (int b=-9;b<=9;b++) 
        printf((abs(b)<a)?"*":" "); 
    printf("\n"); 
}


Iemand nog korter :? :)
Even uit het hoofd; die eerste kan wel wat korter:
C++:
1
2
3
4
5
6
for (int a=0;a<9;a++) 
{ 
    for (int b=8;b-->0;b) 
        cout << (a<b)? " " : "*"; 
    cout << '\n';
}

Ten eerste zijn je for-lusjes nu iets korter en ten tweede heb ik je printf()'s vervangen door cout<<, wat toch weer twee karakters scheelt (en ook echte C++ code is). Ik neem trouwens aan dat whitespace niet meetelt. (Nu moet ik echt iostream.h includen in plaats van cstdio, wat de winst weer wat terugbrengt, maar ok).

Het tweede voorbeeld kan op soortgelijke manier ingekort worden.

Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 20:29

.oisyn

Moderator Devschuur®

Demotivational Speaker

Soultaker: Hoe wil je die strings dan concateneren? Dat kan in principe alleen @ runtime, met strcat () of met std::string. Voor zover ik weet hebben de hedendaagse compilers nog altijd geen weet van de intrinsics van strcat () of std::string, waardoor het altijd zal vertalen naar een runtime concatenatie

Met macro's kan het natuurlijk wel, want iets als "a" "b" "c" zal gewoon geparsed worden als "abc". Maar ja, je kunt met macro's weer niet recursief werken :)

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!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 19:25
.oisyn schreef op 14 April 2003 @ 12:43:
Hoe wil je die strings dan concateneren? Dat kan in principe alleen @ runtime, met strcat () of met std::string. Voor zover ik weet hebben de hedendaagse compilers nog altijd geen weet van de intrinsics van strcat () of std::string, waardoor het altijd zal vertalen naar een runtime concatenatie

Met macro's kan het natuurlijk wel, want iets als "a" "b" "c" zal gewoon geparsed worden als "abc". Maar ja, je kunt met macro's weer niet recursief werken :)
Mja, daarom kwam ik er ook niet uit. Jammer, want het echte voordeel van de compiler het werk laten doen is dan een beetje weg.

Kun je trouwens strings doorgeven als template argumenten? En zo ja, kun je er dan ook at-compile-time mee concateren? (Zoals ook met getallen kan, die je at-compile-time kunt optellen enzo) Dan zou je namelijk een accumulatieparameter op je template kunnen zetten.

[ Voor 4% gewijzigd door Soultaker op 14-04-2003 12:47 ]


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 20:29

.oisyn

Moderator Devschuur®

Demotivational Speaker

Je kunt idd een const char * als template argument gebruiken. Maar het probleem zit m nou juist in het feit dat er geen taalconstructie is om strings te concateneren. Rekenen met integer constanten kan omdat dat @ compiletime te doen is, zodra je een variabele gaat gebruiken krijg je een error.

Iets als:
C++:
1
int a = 2 + 3;


zal ook direct vertaald worden naar a = 5
Er is echter geen soortgelijke constructie om 2 strings aan elkaar te concateneren (dat vereist het gebruik van een buffer, die al dan niet gealloceerd moet worden, waarna vervolgens de 2 strings achter elkaar gekopieerd worden), en dus lijkt het me ook onmogelijk dat dat weggeoptimalizeerd wordt met templates

Het enige wat je kunt doen is denk ik een buffer zelf vullen met chars, waardoor de hele template constructie uiteindelijk vertaald wordt naar een rijtje for-lusjes waarin je de buffer vult. En dan maar hopen dat de compiler dat begrijpt en optimalizeert door gewoon de buffer direct te initializeren met de juiste characters en de hele for-lus achterwege te laten

Maar ik vraag me af of iets als dit ook zo geoptimalizeert wordt:
C++:
1
2
3
char buf[100];
for (int i = 0; i < 10; i++)
    buf[i] = 'a';


ik heb hier geen goede compiler tot mijn beschikking, misschien dat iemand naar de assembly output van bovenstaande code kan kijken?

.edit: even mijn shell account op xs4all geabused, gcc 2.95.3 met optimalisatie -O3 optimaliseert de for-lus dus niet weg

[ Voor 38% gewijzigd door .oisyn op 14-04-2003 13:04 ]

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!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 19:25
.oisyn schreef op 14 april 2003 @ 12:53:
Je kunt idd een const char * als template argument gebruiken. Maar het probleem zit m nou juist in het feit dat er geen taalconstructie is om strings te concateneren. Rekenen met integer constanten kan omdat dat @ compiletime te doen is, zodra je een variabele gaat gebruiken krijg je een error.
In principe zou een compiler ook ("abc" + "def") kunnen reduceren tot ("abcdef"), ware het niet dat die +-operator in de taal niet op const char[]'s gedefinieerd is (zoals 'ie dat wel op getallen is, bijvoorbeeld). Dat is natuurlijk jammer. In principe is het alloceren niet echt een probleem; dat kan de compiler voor "abc" en "def" afzonderlijk ook wel. Het probleem zit mijns inziens in het ontbreken van een taalconstructie voor het concateren van strings: de talen C en C++ kennen immers geen string type (die functionaliteit wordt geimplementeerd met behulp van arrays/pointers in C en een 'gewone' klasse in C++).
Het enige wat je kunt doen is denk ik een buffer zelf vullen met chars, waardoor de hele template constructie uiteindelijk vertaald wordt naar een rijtje for-lusjes waarin je de buffer vult. En dan maar hopen dat de compiler dat begrijpt en optimalizeert door gewoon de buffer direct te initializeren met de juiste characters en de hele for-lus achterwege te laten
Maar dat is flauw. Een beetje compiler kan een for-lusje zelf namelijk ook wel inlinen, daar heb je geen templates voor nodig. Het meest vervelende is nog wel dat een compiler dat nooit hoeft te doen; het is maar een optimalisatie. Als je met behulp van je template parameters strings zou kunnen concateneren, had je de garantie dat elke C++ compiler die die functionaliteit ondersteund, de 'optimalisatie' uitvoert.
Maar ik vraag me af of iets als dit ook zo geoptimalizeert wordt:
C++:
1
2
3
char buf[100];
for (int i = 0; i < 10; i++)
    buf[i] = 'a';


ik heb hier geen goede compiler tot mijn beschikking, misschien dat iemand naar de assembly output van bovenstaande code kan kijken?

.edit: even mijn shell account op xs4all geabused, gcc 2.95.3 met optimalisatie -O3 optimaliseert de for-lus dus niet weg
GCC 3.2.2 doet 't pas als ik -funroll-loops meegeef. (En dan moet ik nog expliciet iets moeilijks met de string doen om te voorkomen dat 'ie die buffer met -O3 helemaal wegoptimaliseert :) ).

[ Voor 7% gewijzigd door Soultaker op 14-04-2003 14:32 ]


Acties:
  • 0 Henk 'm!

  • Rataplan
  • Registratie: Oktober 2001
  • Niet online

Rataplan

per aspera ad astra

Soultaker schreef op 14 April 2003 @ 12:41:
C++:
3
for (int b=8;b-->0;b) 
Ik doelde eik niet op cosmetische verkortingen: dan had je ook nog eea aan spaties, tabs en newlines kunnen weghalen. Het verschuiven van de grenzen van de for's is natuurlijk wel handig, sneller ook, dacht ik. Wat het obfuscaten van de tweede "for" voor nut heeft boven
C++:
3
for (int b=8;b>0;b--)
mag je trouwens ff toelichten ;)

***

Geef ik zelf maar een antwoord:
C++:
1
2
3
int d=9;
for(int a=0;a<d;a++)
    cout << string(d-a, ' ') + string(a, '*') + '\n';
...met cout, want daar heb je ook wel weer een punt ;)
Voor een piramide wijzig je regel 3 in
C++:
3
    cout << string(d-a, ' ') + string(a*2+1, '*') + '\n';


Journalism is printing what someone else does not want printed; everything else is public relations.


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 20:29

.oisyn

Moderator Devschuur®

Demotivational Speaker

Soultaker schreef op 14 April 2003 @ 14:29:
[...]

In principe zou een compiler ook ("abc" + "def") kunnen reduceren tot ("abcdef"), ware het niet dat die +-operator in de taal niet op const char[]'s gedefinieerd is (zoals 'ie dat wel op getallen is, bijvoorbeeld). Dat is natuurlijk jammer. In principe is het alloceren niet echt een probleem; dat kan de compiler voor "abc" en "def" afzonderlijk ook wel. Het probleem zit mijns inziens in het ontbreken van een taalconstructie voor het concateren van strings: de talen C en C++ kennen immers geen string type (die functionaliteit wordt geimplementeerd met behulp van arrays/pointers in C en een 'gewone' klasse in C++).
dat is ook precies wat ik bedoelde te zeggen :)
Je hebt geen native concatenatie operator voor strings die begrepen wordt door de compiler... da's in dit geval erg jammer. De vraag is natuurlijk in hoeverre dat in het echte programmeerleven nodig is ;)

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!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 19:25
Rataplan schreef op 14 April 2003 @ 14:35:
Ik doelde eik niet op cosmetische verkortingen: dan had je ook nog eea aan spaties, tabs en newlines kunnen weghalen.
Als het je om de cosmetica ging had je wel eens gelijk C++-style I/O mogen gebruiken! ;)
Wat het obfuscaten van de tweede "for" voor nut heeft boven
C++:
3
for (int b=8;b>0;b--)
mag je trouwens ff toelichten ;)
Ten eerste is het 1 karakter korter; tenminste, dat zou het zijn geweest als ik niet vergeten was die laatste b weg te halen (die absoluut niets doet nu). Dat was echter niet de reden: omdat ik in het eerste lusje a 1tje kleiner had gemaakt (van 0 t/m 8 ipv 1 t/m 9) moest ik b ook 1tje kleiner maken om de vergelijking goed te laten gaan (en dezelfde vorm als uitvoer te krijgen). Aangezien ik de conditie "b > 0" niet wilde vervangen door "b > -1" of "b >= 0" (wat een karakter meer kost) kon ik met de post-decrement operator het lusje hetzelfde houden en toch in de lus een 1 kleinere waarde van b hebben.

Het had trouwens dit moeten zijn:
C++:
1
for (int b=9;b-->0;)  { ... } 

Die 8 stond er nog van een andere gedachtengang. :)

[ Voor 43% gewijzigd door Soultaker op 14-04-2003 14:45 ]


Acties:
  • 0 Henk 'm!

Verwijderd

>waarin ze je inzicht willen testen

je bent geloof ik dus niet door de test heengekomen.. :)

Acties:
  • 0 Henk 'm!

  • Rataplan
  • Registratie: Oktober 2001
  • Niet online

Rataplan

per aspera ad astra

Soultaker schreef op 14 April 2003 @ 14:41:
Als het je om de cosmetica ging had je wel eens gelijk C++-style I/O mogen gebruiken! ;)
Ging het dus ! om :D
C++:
1
for (int b=9;b-->0;)  { ... } 
Helder en idd sneller; al heb ik ook de jongste loot weer niet afgeregeld op juiste hoeveelheden regels en/of sterretjes, dat mag iemand doen die de output werkelijk waardeert ;) Het ging mij hier alleen even om de structuur van de code, niet om de exacte ranges. * Rataplan is vandaag {R-,K-}

...geloof ik. Da's ook al zo'n tien jaar geleden...


Journalism is printing what someone else does not want printed; everything else is public relations.


Acties:
  • 0 Henk 'm!

  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 13-09 00:05
Je kunt natuurlijk ook gebruik maken van de string ctor die een string maakt van N keer karakter C, dan hoef je zelf die inner loop niet te schrijven
offtopic:
maar ik vergeet altijd of dat nou std::string(size_t N,char C) of std::string(char C, size_t N ) is.

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


Acties:
  • 0 Henk 'm!

  • Rataplan
  • Registratie: Oktober 2001
  • Niet online

Rataplan

per aspera ad astra

MSalters schreef op 14 April 2003 @ 22:45:
Je kunt natuurlijk ook gebruik maken van de string ctor die een string maakt van N keer karakter C
Oh ja joh? ;)

offtopic:
std::string(size_t N,char C) dus :)


Journalism is printing what someone else does not want printed; everything else is public relations.


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 20:29

.oisyn

Moderator Devschuur®

Demotivational Speaker

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!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 20:29

.oisyn

Moderator Devschuur®

Demotivational Speaker

MSalters schreef op 14 April 2003 @ 22:45:
Je kunt natuurlijk ook gebruik maken van de string ctor die een string maakt van N keer karakter C, dan hoef je zelf die inner loop niet te schrijven
offtopic:
maar ik vergeet altijd of dat nou std::string(size_t N,char C) of std::string(char C, size_t N ) is.
Weet jij trouwens of partial specialization bij function templates mogelijk zijn? Want zowel Comeau als gcc geven errors, en ik kan er ook niets over vinden in de standaard. Nou zegt het feit dat ik het niet kan vinden waarschijnlijk wel genoeg, maar ik wil het even zeker weten ;)

zie ook [rml].oisyn in "[ c++] Tekenen met geneste for loops"[/rml]

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!

  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 13-09 00:05
Nee, dat werd te lastig te parsen/implementeren in combinatie met functie overloading, als ik me de reden goed herinner. De workaround is natuurlijk triviaal; gebruik function objects.

PS. Ik vermoed dat je wel degelijk strings in templates compile-time kunt concateneren. Niet de "" vorm natuurijk, maar door middel van template meta programming een lijst van constante chars te creeren. Zoiets als een String<i> die een static const char bevat, en een String<i-1>. De enige truc die je dan nog nodig hebt is het meta-gebruik van zo'n object als char[]-initializer, en die ontschiet me nu.

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 20:29

.oisyn

Moderator Devschuur®

Demotivational Speaker

Mja dat kan natuurlijk wel, gewoon een hele lijst van die String objecten wat members van elkaar zijn, zodat je in het geheugen een directe lijst van chars hebt... Alleen heb je dan wel de garantie dat ze allemaal op elkaar volgen, en dat er dus geen alignment in zit?

Een string van N * de char C zou dan zoiets worden:

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
template<int N, char C> struct String
{
    const char c;
    String<N - 1, C> rest;

    String () : c (C) { }
    operator const char * () const
    {
        return &c;
    }
};

template <char C> struct String<0, C>
{
    const char c;

    String () : c (0) { }
};

int main ()
{
    std::cout << String<10, 'a'> () << std::endl;
}


.edit: woei dit werkt >:)
Niet zoals het hier staat overigens, de String die ik hier maak is local, en MSVC++ 7.1 maakt er dit van:
GAS:
1
2
3
4
5
6
7
8
9
10
11
    mov al, 97
    mov BYTE PTR $T10345[esp+16], al
    mov BYTE PTR $T10345[esp+17], al
    mov BYTE PTR $T10345[esp+18], al
    mov BYTE PTR $T10345[esp+19], al
    mov BYTE PTR $T10345[esp+20], al
    mov BYTE PTR $T10345[esp+21], al
    mov BYTE PTR $T10345[esp+22], al
    mov BYTE PTR $T10345[esp+23], al
    mov BYTE PTR $T10345[esp+24], al
    mov BYTE PTR $T10345[esp+25], al


maar als je een globale var definieert dan wordt dat dit:

GAS:
1
2
3
4
5
6
7
8
9
10
    DB  061H
    DB  061H
    DB  061H
    DB  061H
    DB  061H
    DB  061H
    DB  061H
    DB  061H
    DB  061H
    DB  00H


En de string die de pyramide functie moet retourneren kun je dus mooi als statische globale variabele definieren, aangezien die een pyramid<5> altijd hetzelfde is, en verder ook onwijzigbaar.

Ik zal zo eens de code tikken :)

[ Voor 43% gewijzigd door .oisyn op 15-04-2003 22:13 ]

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!

  • Buffy
  • Registratie: April 2002
  • Laatst online: 26-12-2024

Buffy

Fire bad, Tree pretty

Soultaker schreef op 14 April 2003 @ 12:37:
[...]

Nu je 't zegt!


[...]

Mja, ik ben hier wel vaker tegenop gelopen. Op de een of andere manier kun je functie-templates niet specialiseren ofzo. Ik werk er altijd omheen door een mooie struct te definieren met een bepaalde methode, en die dan te specialiseren.

[...]
Elke template argument van een functie template moet gebruikt worden in de type definitie van de functie argumenten.
Dit komt omdat template functies overloaded functies zijn die geselecteerd worden aan de hand van de type van hun argumenten en niet op basis van template argumenten.
Met een struct er omheen werkt het wel omdat member functies geselecteerd worden aan de hand van hun classtype die je wel kan specificeren m.b.v. template argumenten.

That which doesn't kill us, makes us stranger - Trevor (AEon FLux)
When a finger points at the moon, the imbecile looks at the finger (Chinese Proverb)


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 20:29

.oisyn

Moderator Devschuur®

Demotivational Speaker

Dawns_sister schreef op 15 April 2003 @ 19:33:
[...]

Elke template argument van een functie template moet gebruikt worden in de type definitie van de functie argumenten.
dat is niet zo, dit is perfecte code:

C++:
1
2
3
4
5
6
7
8
9
template <class T, int I> void func_zonder_argumenten ()
{
    T array[I];
}

int main ()
{
    func_zonder_argumenten<int, 10> ();
}


Het bepalen van de juiste functie hoeft dus ook niet per se door de argumeten, je kunt het expliciet opgeven bij de aanroep, net als bij class/struct templates

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!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 20:29

.oisyn

Moderator Devschuur®

Demotivational Speaker

.oisyn schreef op 15 April 2003 @ 18:08:
Ik zal zo eens de code tikken :)
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
#include <iostream>

template <int N, char C> struct String
{
    const char c;
    String<N - 1, C> rest;

    String () : c (C) { }
};

template <char C> struct String<1, C>
{
    const char c;

    String () : c (C) { }
};

template <int ROWS, int SPACES> struct PyramidStart
{
    PyramidStart<ROWS - 1, SPACES + 1> top;
    String<SPACES, ' '> space;
    String<ROWS * 2 - 1, '*'> base;
    String<1, '\n'> newline;
};

template <int ROWS> struct PyramidStart<ROWS, 0>
{
    PyramidStart<ROWS - 1, 1> top;
    String<ROWS * 2 - 1, '*'> base;
    String<1, '\n'> newline;
};

template <int SPACES> struct PyramidStart<1, SPACES>
{
    String<SPACES, ' '> space;
    String<1, '*'> base;
    String<1, '\n'> newline;
};

template <> struct PyramidStart<1, 0>
{
    String<1, '*'> base;
    String<1, '\n'> newline;
};

template <int ROWS> struct Pyramid
{
    PyramidStart<ROWS, 0> pyramid;
    String<1, '\0'> eos;

    operator const char * () const { return reinterpret_cast<const char *> (this); }

    static Pyramid thePyramid;
};

template <int ROWS> Pyramid<ROWS> Pyramid<ROWS>::thePyramid;

template <int ROWS> const char * generatePyramid ()
{
    return Pyramid<ROWS>::thePyramid;
}


int main ()
{
    std::cout << generatePyramid<5> () << std::endl;
    return 0;
}


Maar helaas :{
De code is nu dermate ingewikkeld dat ie voor initializatie van Pyramid<5>::thePyramid gewoon de constructor aanroept. Die constructor ziet er zo uit:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
    mov cl, 42                  ; 0000002aH
    mov dl, 32                  ; 00000020H
    mov BYTE PTR [eax], dl
    mov BYTE PTR [eax+1], dl
    mov BYTE PTR [eax+2], dl
    mov BYTE PTR [eax+3], dl
    mov BYTE PTR [eax+4], cl
    push    ebx
    mov bl, 10                  ; 0000000aH
    mov BYTE PTR [eax+5], bl
    mov BYTE PTR [eax+6], dl
    mov BYTE PTR [eax+7], dl
    mov BYTE PTR [eax+8], dl
    mov BYTE PTR [eax+9], cl
    mov BYTE PTR [eax+10], cl
    mov BYTE PTR [eax+11], cl
    mov BYTE PTR [eax+12], bl
    mov BYTE PTR [eax+13], dl
    mov BYTE PTR [eax+14], dl
    mov BYTE PTR [eax+15], cl
    mov BYTE PTR [eax+16], cl
    mov BYTE PTR [eax+17], cl
    mov BYTE PTR [eax+18], cl
    mov BYTE PTR [eax+19], cl
    mov BYTE PTR [eax+20], bl
    mov BYTE PTR [eax+21], dl
    mov BYTE PTR [eax+22], cl
    mov BYTE PTR [eax+23], cl
    mov BYTE PTR [eax+24], cl
    mov BYTE PTR [eax+25], cl
    mov BYTE PTR [eax+26], cl
    mov BYTE PTR [eax+27], cl
    mov BYTE PTR [eax+28], cl
    mov BYTE PTR [eax+29], bl
    mov BYTE PTR [eax+30], cl
    mov BYTE PTR [eax+31], cl
    mov BYTE PTR [eax+32], cl
    mov BYTE PTR [eax+33], cl
    mov BYTE PTR [eax+34], cl
    mov BYTE PTR [eax+35], cl
    mov BYTE PTR [eax+36], cl
    mov BYTE PTR [eax+37], cl
    mov BYTE PTR [eax+38], cl
    mov BYTE PTR [eax+39], bl
    pop ebx;


Toch wazig dat ie dat niet optimaliseert naar dword mov instructies. Hoewel dat door verkeerde alignment natuurlijk weleens verkeerd kan uitpakken

Dit was dus MSVC++ 7.1 (visual studio .net 2003 RC3)

Dus helaas... misschien dat iemand kan proberen wat de andere compilers ervan maken?

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!

  • darthdrinker
  • Registratie: November 1999
  • Laatst online: 24-07 10:25

darthdrinker

HELP!

ROFL

Is het misschien een idee om een wedstrijd te doen.
We bedenken een zo makkelijk mogelijke opdracht en dan moeten we die op een zo ingewikkeld mogelijke manier oplossen. Wat denken jullie ervan?

Iemand doodmaken met een blije mus.....


Acties:
  • 0 Henk 'm!

  • hobbit_be
  • Registratie: November 2002
  • Laatst online: 04-07 12:07
.oisyn: mischien het geval waar C++ een tikkeltje overkill is ;) - wel mooie oefening en ik ben ervan overtuigd dat dat het geval is :)

Acties:
  • 0 Henk 'm!

  • Buffy
  • Registratie: April 2002
  • Laatst online: 26-12-2024

Buffy

Fire bad, Tree pretty

.oisyn schreef op 15 April 2003 @ 21:52:
[...]


dat is niet zo, dit is perfecte code:

[snip]

Het bepalen van de juiste functie hoeft dus ook niet per se door de argumeten, je kunt het expliciet opgeven bij de aanroep, net als bij class/struct templates
Ahhh, dat is gemeen!
C/C++ Users Journal:
Type Arguments of Function Templates

Explicit specification of template arguments for function templates is a relatively new language feature, which was added during C++ standardization. When you look at the ARM (Annotated Reference Manual) [1], which is the reference for pre-standard C++, you will find that initially there was no way to tell the compiler which types to use as template arguments for instantiation of a function template. In those days, a template such as the one shown below was illegal.

template <class T>
T* create();
Ik wordt oud :'(.
Was laatst ook zo mistified over het keyword typename.

Wat betreft "partial template specialization" van een function template. Na wat zoeken blijkt dat inderdaad nog niet toegestaan. De reden is dat het niet nodig is/was omdat het meestal ook bereikt kan worden m.b.v. normale overloading van functies. Alleen in situatie met explicite template argument qualificatie (waarvan ik niet wist dat dat kon ;)) zoals jij gebruikte in je voorbeeld (drawPyramid<5, 0>) kan het handig zijn.

Probleem is dat dan het resolven van de juiste template functie specificatie nog ingewikkelder wordt en voor programeurs moeilijk voorspelbaar terwijl de extra functionaliteit klein is.
partial template specialization and functions; virtual template-functions :
I think that the problem (of what we want) stems from the way that
gifted individuals have discovered what else they can do with templates
(metaprogramming etc.) which was not in the conscious minds of those
doing the original language design. We are dealing with a kind of
emergent behaviour (think of the Mandelbrot Set if you are unfamiliar
with that term). We are already coping with a good deal of unexpected
(well I think it is) usage of templates and feel it is time we stood
back and considered if we can separate the static polymorphism that I
think was the main design motive for templates from the rest and then
provide better tools for the rest.
offtopic:
Sorry voor het offtopic gaan. Ik had even een leer moment :)

That which doesn't kill us, makes us stranger - Trevor (AEon FLux)
When a finger points at the moon, the imbecile looks at the finger (Chinese Proverb)


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 20:29

.oisyn

Moderator Devschuur®

Demotivational Speaker

Het vervelende is dat het met overloading idd wel gaat, maar er nu integral template arguments worden gebruikt ipv types. Als je een template functie hebt, waarbij de argument het type is van het template argument, dan kun je in principe een gespecializeerde functie maken, zonder dat je daar een template specializatie voor maakt

Zoals gewoonlijk zal mijn taalgebruik wel weer onbegrijpelijk zijn :P, dus een voorbeeldje:
C++:
1
2
3
4
5
6
7
template <class T> void func (const T & t)    // generieke functie
{
}

void func (const int & t)    // specialisatie
{
}


er werden echter integral template arguments gebruikt, en er is geen mogelijkheid om bijvoorbeeld dit te doen:

C++:
1
2
3
4
5
6
7
8
void func (int i)    // generieke functie
{
}

// specialisatie, die moet worden aangeroepen als het argument 0 is:
void func (0)
{
}


(dit in tegenstelling tot bijvoorbeeld functionele talen)
Nou is dit simpelweg te controleren door in de eerste functie te kijken of i gelijk aan 0 is, maar dat wordt dan een runtime check, en dat was hier nou net weer niet de bedoeling :)

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!

  • twit
  • Registratie: September 2002
  • Laatst online: 09:17
Ook al gaat me dit inmiddels ver boven mijn pet wil ik toch even zeggen dat ik het zeer interessant vind wat een tal voor mogelijkheden er voor dit probleem is. Is dit toeval of is dat bij iedere programmeer opdracht eigenlijk wel het geval ?

gutta cavat lapidem non vi, sed saepe cadendo. Sic homo fit doctus, non vi, sed saepe legendo


Acties:
  • 0 Henk 'm!

  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 13-09 00:05
Dawns_sister schreef op 16 april 2003 @ 15:22:
Ik wordt oud :'(.
Was laatst ook zo mistified over het keyword typename.
Wordt gefixed, vorige week is (voorlopig) besloten dat je typename voor elke qualified-id mag zetten, dwz die A::B dingen, dus ook als A geen dependent name is.

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


Acties:
  • 0 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 19:25
twit schreef op 16 april 2003 @ 16:53:
Ook al gaat me dit inmiddels ver boven mijn pet wil ik toch even zeggen dat ik het zeer interessant vind wat een tal voor mogelijkheden er voor dit probleem is. Is dit toeval of is dat bij iedere programmeer opdracht eigenlijk wel het geval ?
Het is om te beginnen erg taalafhankelijk. Ik denk dat er weinig programmeertalen zijn die zo rijk aan mogelijkheden zijn als C++ en Perl, waarbij "rijk" in deze zin niet (uitsluitend) positief is.

Verder geldt voor elk niet-triviaal programmerprobleem (en het is maar de vraag of het genoemde probleem in die categorie valt) dat er zoveel (misschien wel oneindig veel) verschillende mogelijkheden voor de implementatie zijn, dat de creativiteit van een menselijke programmeur noodzakelijk is. Zelfs voor formeel gespecificeerde problemen kan niet automatisch een implementatie worden ontwikkeld, omdat de keuzemogelijkheden bij het ontwerp van de implementatie te divers zijn.
Pagina: 1