Check alle échte Black Friday-deals Ook zo moe van nepaanbiedingen? Wij laten alleen échte deals zien

[C++] Generieke functieaanroep

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

  • liquid_ice
  • Registratie: Februari 2001
  • Laatst online: 19-11 07:22
Ik wil een soort vertaal library (voor little / big endian enzo) maken, waarvan een functie van worden aangeroepen met 1 of meerdere variabelen. Om het zo universeel mogelijk te krijgen ben ik eigelijk opzoek naar een generieke functie aanroep.

Ik zou ietrs kunnen doen als
code:
1
2
3
4
5
6
7
8
9
10
11
Functie 1:
VertaalInt(int)

Functie 2:
VertaalInt(int, int)

Functie 3:
VertaalInt(int, int, int)

Functie n:
......


Als ik naast ints ook chars, strings, bool, enum's enz...
wil ondersteunen dan worden het oneindig veel functies.
Hoe kan ik mijn functie aanroep op een generieke manier laten gebeuren om zoveel mogelijk flexibiliteit te krijgen?

Klus page: http://klusthuis.blogspot.com


  • Boy
  • Registratie: November 2001
  • Laatst online: 19:21

Boy

www.byoscoop.nl

Ik weet wel ongeveer hoe het werkt...maar met google vind je het ook zo:

http://www.softwareacadem...20Number%20of%20Arguments

nog niet zelf helemaal doorgelezen maar moet zoiets zijn wat je zoekt...

edit: deze misschien duidelijker : http://www.mycplus.com/tutorial.asp?TID=177

[ Voor 32% gewijzigd door Boy op 28-09-2007 11:45 ]

Naar de bioscoop? => gebruik de app op Byoscoop.nl


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

.oisyn

Moderator Devschuur®

Demotivational Speaker

Daar heb je niets aan, dan weet je de types namelijk niet.

Wat je kunt doen is gebruik maken van templates, dan hoef je maar N functies te schrijven om N verschillende parameters te ondersteunen.
C++:
1
2
3
4
template<class T1> void Vertaal(T1 & p1);
template<class T1, class T2> void Vertaal(T1 & p1, T2 & p2);
template<class T1, class T2, class T3> void Vertaal(T1 & p1, T2 & p2, T3 & p3);
// etc


Maar waarom houd je het niet gewoon bij (overloaded) functies met maar 1 parameter? Ik bedoel, je kunt natuurlijk ook gewoon makkelijk vanuit code meerdere keren die functie aanroepen voor verschillende variabelen.

[ Voor 20% gewijzigd door .oisyn op 28-09-2007 11:47 ]

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.


  • Boy
  • Registratie: November 2001
  • Laatst online: 19:21

Boy

www.byoscoop.nl

.oisyn schreef op vrijdag 28 september 2007 @ 11:46:
Daar heb je niets aan, dan weet je de types namelijk niet.

Wat je kunt doen is gebruik maken van templates, dan hoef je maar N functies te schrijven om N verschillende parameters te ondersteunen.
C++:
1
2
3
4
template<class T1> void Vertaal(T1 & p1);
template<class T1, class T2> void Vertaal(T1 & p1, T2 & p2);
template<class T1, class T2, class T3> void Vertaal(T1 & p1, T2 & p2, T3 & p3);
// etc


Maar waarom houd je het niet gewoon bij (overloaded) functies met maar 1 parameter? Ik bedoel, je kunt natuurlijk ook gewoon makkelijk vanuit code meerdere keren die functie aanroepen voor verschillende variabelen.
stel dat je weet dat alle variabelen wel hetzelfde type hebben, kun je dan wel

C++:
1
template<class T1> void Vertaal(T1 & p1, ...);

doen?

Naar de bioscoop? => gebruik de app op Byoscoop.nl


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

.oisyn

Moderator Devschuur®

Demotivational Speaker

Dat kan idd wel, maar het is niet erg typesafe. Niemand waarschuwt jou als je eerste argument een float is en je tweede een std::string oid.

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.


  • PiepPiep
  • Registratie: Maart 2002
  • Laatst online: 17-11 14:00
Boy schreef op vrijdag 28 september 2007 @ 11:48:
[...]


stel dat je weet dat alle variabelen wel hetzelfde type hebben, kun je dan wel

C++:
1
template<class T1> void Vertaal(T1 & p1, ...);

doen?
Alleen weet je op deze manier niet hoeveel variabelen je krijgt.
C++:
1
template<class T1> void Vertaal(int aantal, T1 & p1, ...);

Zoiets zou het dan worden.

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


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

.oisyn

Moderator Devschuur®

Demotivational Speaker

Eigenlijk is het gewoon wachten op C++09's variadic templates ;)

C++:
1
template<class... T> void Vertaal(T... & args);

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.


  • liquid_ice
  • Registratie: Februari 2001
  • Laatst online: 19-11 07:22
.oisyn schreef op vrijdag 28 september 2007 @ 11:46:
Wat je kunt doen is gebruik maken van templates, dan hoef je maar N functies te schrijven om N verschillende parameters te ondersteunen.
C++:
1
2
3
4
template<class T1> void Vertaal(T1 & p1);
template<class T1, class T2> void Vertaal(T1 & p1, T2 & p2);
template<class T1, class T2, class T3> void Vertaal(T1 & p1, T2 & p2, T3 & p3);
// etc
Ok, dus als ik max 10 parameters wil ondersteunen zijn het maar 10 functies, das wel mooi :D
Maar waarom houd je het niet gewoon bij (overloaded) functies met maar 1 parameter? Ik bedoel, je kunt natuurlijk ook gewoon makkelijk vanuit code meerdere keren die functie aanroepen voor verschillende variabelen.
Intern wilde ik dat doen. Elke variabele laten vertalen door een speciale functie, maar voor de interface liever niet. Het word een aangepaste XDR vertaal class (voor de geintereseerden), waarbij het grote geheel is voor als iemand op een Intel met windows een functie aanroept met een aantal params en de juiste functie moet worden uitgevoerd (met de juiste waarden natuurlijk) op een ander systeem (mogelijk arm, motorola oid) met mogelijk andere besturingssysteem en een ander endian systeem.
.oisyn schreef op vrijdag 28 september 2007 @ 13:01:
Eigenlijk is het gewoon wachten op C++09's variadic templates ;)

C++:
1
template<class... T> void Vertaal(T... & args);
C++09's variadic??
ken ik niet, wat is dat?

Klus page: http://klusthuis.blogspot.com


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

H!GHGuY

Try and take over the world...

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
template<class T> bool Vertaal(T& arg)
{
  return false; // unknown T
}

bool Vertaal(int& arg)
{
   arg = htonl(arg);
   return true;
}

template<class T> Vertaal(std::vector<T>& args)
{
   for (std::vector<T>::iterator begin=args.begin(), end=args.end(); begin != end; ++begin)
      Vertaal(*begin);
}


Boost heeft macro's die overloads kunnen maken voor 1->n parameters. Of die hier bruikbaar zijn is echter nog de vraag.

ASSUME makes an ASS out of U and ME


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

.oisyn

Moderator Devschuur®

Demotivational Speaker

liquid_ice schreef op vrijdag 28 september 2007 @ 14:17:
C++09's variadic??
ken ik niet, wat is dat?
C++09 is de nieuwe C++ standaard die in 2009 verwacht wordt. "Variadic" staat voor de ... syntax, functies die het gebruiken (zoals printf) heten variadic functies. C++09 krijgt zogenaamde 'variadic templates', waarbij het aantal template argumenten variabel kan zijn. Op die manier kun je dus echte type-safe variadic functies maken, omdat je een object meekrijgt waarop je (tijdens compile-time) de typen en het aantal argumenten op kunt vragen. Zie ook hier.

Een mooie implementatie zou dus zijn:
C++:
1
2
3
4
5
6
7
8
9
void Vertaal(int & i) { i = htonl(i); }
void Vertaal(float & f) { /* etc */ }

template<class T, class... Args>
void Vertaal(T & head, Args&... tail)
{
    Vertaal(head);
    Vertaal(tail...);
}


Maar goed, nog eventjes wachten dus, eerst totdat de standaard is geformuleerd en daarna tot je favo compiler boer 'm geïmplementeerd heeft ;)

[ Voor 19% gewijzigd door .oisyn op 28-09-2007 15:11 ]

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.


  • liquid_ice
  • Registratie: Februari 2001
  • Laatst online: 19-11 07:22
alleen jammer dat de opdrachtgever waarschijnlijk niet wil wachten to '09 ergens...
maar voor toekomstige oplossingen is het prachtig

Klus page: http://klusthuis.blogspot.com


  • writser
  • Registratie: Mei 2000
  • Laatst online: 28-11 15:44
Als je niet weet hoeveel argumenten je functie krijgt, waarom gebruik je dan geen std::vector? Of (minder netjes) een pointer naar een array met argumenten? Een functie voor integers bijv:

C++:
1
2
3
4
5
6
7
8
int som(std::vector<int> & lijst) {
  std::vector<int>::iterator i;
  int som = 0;
  for (i = lijst.begin(); i != lijst.end(); i++) {
    som += *i;
  }
  return som;
}


Dat is toch veel generieker? Eventueel kun je deze functie met templates zo aanpassen dat hij ook werkt op floats, doubles en al je eigen datatypes. Misschien kun je iets vertellen over de context waarin je deze functie nodig hebt. Ik stel me namelijk zo'n soort code voor: :P

C++:
1
2
3
4
5
6
int getal0 = 442;
int getal1 = 33;
..
int getal99 = 21;

doeIets(getal0, getal1, getal2, getal3, ....);

Waarbij een lijst of een andere datastructuur een veel logischere oplossing is.

[ Voor 23% gewijzigd door writser op 28-09-2007 17:37 ]

Onvoorstelbaar!


  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 13-09 00:05
Gewoon de std::cout truc gebruiken?
C++:
1
Vertaal << a << b << c;

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


  • liquid_ice
  • Registratie: Februari 2001
  • Laatst online: 19-11 07:22
Dus (als ik het goed begrijp) kan je geen typesafe oplossing maken voor 1 functie met onbekend aantal params(zolang we niet die '09 uitbreiding hebben).
Voor een typesafe oplossing moet je dus templates gebruiken zoals .oisyn in z'n eerste post heeft gemeld.

over de context, zoek maar eens op XDR (eXternal Data Representation) of bezoek http://www.unet.univie.ac...rggd/progcomc/xdr_ovw.htm

@MSalters, geen idee, maar ik verwacht dat dat niet typesafe is.

Klus page: http://klusthuis.blogspot.com


  • Orphix
  • Registratie: Februari 2000
  • Niet online
liquid_ice schreef op zaterdag 29 september 2007 @ 00:22:
@MSalters, geen idee, maar ik verwacht dat dat niet typesafe is.
Het is operator overloading, en dus typesafe (als je wilt). Daarnaast vind ik dit veruit de meeste elegante oplossing.

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

H!GHGuY

Try and take over the world...

C++:
1
2
3
4
5
6
7
8
9
#define Vertaal(...) do { CVertaal(), __VA_ARGS__; } while (false);

class CVertaal()
{
   public:
   CVertaal() {}
   CVertaal& operator,(int& a) { a = ntohl(a); return *this}
   CVertaal& operator,(float& a) {...; return *this; }
}


Of het proper is, is een andere vraag natuurlijk, maar creatief is het wel :P

Als je echt functies wil kun je beter voor templates en vector's gaan voor meerdere argumenten, ofwel zoals MSAlters aangeeft operator<< overloaden

ASSUME makes an ASS out of U and ME


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

.oisyn

Moderator Devschuur®

Demotivational Speaker

vararg macro's in C++? Dacht het niet ;)

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.


  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Of iets dat lijkt op deze manier hoe ik het ooit heb geschreven:

Oh, ik begrijp nu pas wat je wilt, je wil types kunnen mixen in 1 functie call. Ik dacht dat alle functies wel dezelfde types wilden. Je wilt een soort php.

In plaats van dit alles zelf uit te vinden kan je ook even de Boost reference door lezen.

(ik heb hier best lang niet gepost eigenlijk... ook een tijd niet met C++ bezig gehouden. Ik heb denk ik al zeker een jaar niet in de standaard gekeken :) )

Anyway, ja gewoon wat michiel zegt lijkt me, de stream libraries zijn niet voor niets zo geschreven. Die zitten behoorlijk goed in elkaar. (standard c++ iostreams and locales, langer&kreft) Eerlijk gezegd denk ik dat je je hele "vertaal" procedure kan implementeren op de bestaande streams.

[ Voor 101% gewijzigd door Zoijar op 30-09-2007 12:02 ]


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

H!GHGuY

Try and take over the world...

.oisyn schreef op zaterdag 29 september 2007 @ 23:23:
vararg macro's in C++? Dacht het niet ;)
gcc en visual studio ondersteunen het, dus waarom niet ;)

ASSUME makes an ASS out of U and ME


  • farlane
  • Registratie: Maart 2000
  • Laatst online: 30-11 00:17
H!GHGuY schreef op zondag 30 september 2007 @ 12:20:
[...]


gcc en visual studio ondersteunen het, dus waarom niet ;)
Vanaf Visual Studio 2005 volgens mij pas

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.


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

H!GHGuY

Try and take over the world...

farlane schreef op zondag 30 september 2007 @ 13:27:
[...]


Vanaf Visual Studio 2005 volgens mij pas
Dat is waarschijnlijk ook wel weer waar.
Anderzijds is het schrijven van die extra macro's nu ook niet het allergrootste probleem als er geen ondersteuning is voor variadic macro's

[ Voor 7% gewijzigd door H!GHGuY op 30-09-2007 17:03 ]

ASSUME makes an ASS out of U and ME


  • liquid_ice
  • Registratie: Februari 2001
  • Laatst online: 19-11 07:22
De eerste manier van .Oisyn spreekt me toch wel echt aan.

Ik heb ooit wat gelezen over RTTI (Real Time Type Identyfication), maar zijn er nog andere manieren om de typen te achterhalen als je een maal in de aangeroepen functie zit?

Zulke templates, is daar nog een speciale manier voor binnen UML om dat weer te geven?
(PS : Of moet ik dit ff in een nieuw topic openen)

[ Voor 114% gewijzigd door liquid_ice op 01-10-2007 12:58 ]

Klus page: http://klusthuis.blogspot.com


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

.oisyn

Moderator Devschuur®

Demotivational Speaker

liquid_ice schreef op maandag 01 oktober 2007 @ 09:53:
Ik heb ooit wat gelezen over RTTI (Real Time Type Identyfication), maar zijn er nog andere manieren om de typen te chaterhalen als je een maal in de aangeroepen functie zit?
Hoe bedoel je, "andere" manieren? RTTI werkt vrij simpel: typeid(myVar) == typeid(int) -> myVar is een int. Maar in jouw usecase is dat wellicht niet handig, het handigst is als je gewoon overloads van de Vertaal() functie maakt van 1 parameter voor elk type dat je wilt kunnen converteren. In die template functie roep je vervolgens voor elke parameter die enkele functie aan. De compiler doet de rest :)

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
void Vertaal(int & i) { /* converteer i */ }
void Vertaal(float & f) { /* converteer f */ }
// etc

template<class T1, class T2> void Vertaal(T1 & p1, T2 & p2)
{
    Vertaal(p1);
    Vertaal(p2);
}

template<class T1, class T2, class T3> void Vertaal(T1 & p1, T2 & p2, T3 & p3)
{
    Vertaal(p1);
    Vertaal(p2); 
    Vertaal(p3);
}

// etc

[ Voor 22% gewijzigd door .oisyn op 01-10-2007 12: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.


  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

run-time type indentification; dat het "real-time" gaat is maar te hopen ;) Maar dat heb je niet nodig hier als je calls statisch zijn. Ik vind de stream oplossing netter imo. Geeft ook duidelijker het model weer: als ik 1 functie aanroep met 10 argumenten verwacht ik dat het parallel gaat oid. Als ik 10 elementen een voor een stream weet ik waar ik aan toe ben.

  • liquid_ice
  • Registratie: Februari 2001
  • Laatst online: 19-11 07:22
@Zoijar, sorry het moet ook run time zijn, foutje van mijn kant.

Klus page: http://klusthuis.blogspot.com

Pagina: 1