Avatar billede mxs Nybegynder
19. januar 2006 - 22:19 Der er 14 kommentarer

hvad er det der sker på compile time med templates?

Hey

Jeg har rodet lidt med compileren, og har jeg da fået lidt ud af, men jeg vil stadig gerne vide hvad der sker med en template på compile time? Og er templates en macro? Jeg vil gerne have noget baggrundsinfo omkring templates emnet. Har i nogen gode artikler med det, som kan findes på nettet? For jeg kan ingen finde.
Avatar billede bertelbrander Novice
19. januar 2006 - 22:43 #1
Lad os tage et eksempel:
#include <iostream>
template <typename T>
T pow2(T a)
{
  return a*a;
}
int main()
{
  double d = 1.2;
  int i = 123;
  std::cout << pow2(d) << ", " << pow2(i) << std::endl;
}

Når kompileren skal kompilere denne kode finder den pow2(d), ser at det er template funktionen pow2 der skal i gang, først i en version hvor T er en double, og siden i en version hvor T er en int. Når compileren møder brug af en template funktion laver den en funktion og objekt kode til denne funktion. Hvis man bruger template funktionen igen med den samme T genbruger den den samme funktion.

Templates adskiller sig fra macro'er i det at de:
1: Bliver til "rigtige" funktioner (medmindre compileren inliner dem).
2: Er typesikre.
3: Argumenterne bliver evalueret som med rigtige funktioner.

Hvis vi havde lavet pow2 som en macro kunne det se sådan ud:
#define pow2(x_) (x_ * x_)
Når så kompileren skulle kompilere ville den lave koden fra før om til:
  std::cout << d*d << ", " << i*i << std::endl;
Hvilket måske er mindre optimalt.

Hvis brugeren havde skrevet:
  int i = 12;
  std::cout << pow2(i++) << std::endl;
er det tydeligt at se forkellen på macro og template.
Avatar billede bertelbrander Novice
19. januar 2006 - 23:17 #2
Avatar billede mxs Nybegynder
19. januar 2006 - 23:19 #3
aaaah ja. Ved en macro skal den lave to pow2 funktioner (tænker i din sidste pow2 eksempel) mens den som en funktions template bare vil genbruge den skabte kode.
Avatar billede bertelbrander Novice
19. januar 2006 - 23:25 #4
Ja.

Den sidste kode:
std::cout << pow2(i++) << std::endl;
Vil  gøre det samme som:
std::cout << i++ * i++ << std::endl;
Hvis pow2 var en macro, hvilket er noget ganske andet en hvis pow2 var en template funktion.

Man kunne også have lavet det første eksempel med:
double pow2(double a)
{
  return a*a;
}

int pow2(int a)
{
  int a*a;
}

template modellen bliver her brugt til at undgå at skrive den samme kode igen og igen.
Avatar billede mxs Nybegynder
19. januar 2006 - 23:31 #5
Jeps, så meget er jeg med :) Jeg var til et foredrag i sidste uge omkring Java 6 og 7. Foredragsholderen, manden der styrede javac brygningen for java, nævnede kort om at java templates og c++ templates ikke er helt det samme. Er det noget du ved noget om Bertel?
Avatar billede mxs Nybegynder
19. januar 2006 - 23:31 #6
Jeg forstod godt selve koden som han smed i hovedet, men hans forklaring omkring hvordan gcc og javac opfattede det har jeg rodet sammen, så jeg vil gerne ha opfrisket det emne nemlig.
Avatar billede bertelbrander Novice
19. januar 2006 - 23:32 #7
Jeg ved ikke noget om java templates, måske kommer Arne forbi?
Avatar billede mxs Nybegynder
19. januar 2006 - 23:34 #8
Hehe ja kan man jo håbe på. Jeg har bare en formodning om at man ikke kan blande primitive typer med objekter (det lyder dog dumt i mit hovede), men manden kom frem til at man bare skulle lave sit array af Objects, som man så senere kunne caste til de man ville.
Avatar billede mxs Nybegynder
19. januar 2006 - 23:36 #9
Men allerede nu kan jeg se det effektive ved templates, sådan mere ned i de specfikke tilfælde. Vil det sige at macro sprog, som fx. Lisp eller andet, er et langsomt sprog?
Avatar billede bertelbrander Novice
20. januar 2006 - 00:29 #10
Hvis jeg skulle gætte på hvordan man laver template funktioner i java skulle det være at man på compile time laver én template funktion som kan behandle alle typer. Det gør at man kan lave sen linkning (man behøver ikke at kende alle typer en template funktion skal kunne bruges med når man compilerer), men det ville også give nogle begrænsninger.

"Macro sprog" som lisp (og python og ruby) er ikke macro sprog på samme måde som macro'er i C++; de er langsomme fordi de skal oversætte sourcen (text format) runtime.
Disse sprog er typisk brugt til andre opgaver, eller man laver biblioteker i f.ex. C++, til at lave de tunge beregninger.
Avatar billede mxs Nybegynder
20. januar 2006 - 01:45 #11
Ahhh ok sådan. Ja man skal vælge et sprog eller flere som er nyttige i sit projekt :)
Avatar billede soreno Praktikant
20. januar 2006 - 12:24 #12
Der findes forskellige kategorier af makrosprog.
Man kan f.eks. skelne dem på det niveau de fungere på.
  - leksikalske makroer (f.eks. CPP - c pre processor)
  - syntaktiske makroer (f.eks. lisp, scheme, c++ templates)
  - semantiske makroer (kender ikke nogle alm. kendte makrosprog)

CPP fungere ved at udskifte tokens og kender dermed ikke noget til syntaksen af C.

C++ Templates fungere på syntaktisk niveau og dermed har man mulighed for at garantere typesikkerhed.

Denne artikel indeholder et survey af makrosprog. Til artiklen er der også nogle præsentationsslides
http://www.brics.dk/bigwig/publications/macro.pdf
http://www.brics.dk/~brabrand/aopl/AoPL.ppt

Denne artikel viser hvordan man kan opnå partiel evaluering med c++ templates.
http://osl.iu.edu/~tveldhui/papers/pepm99/


19/01-2006 23:31:03 skriver du om Java templates. Mener du Java generics ?
(Jeg kender ikke til indholdet af Java6-7 og spørger måske dumt..)


Her er et eksempel på partiel evaluering med c++ templates.
#include <iostream>

template<int N> class Fib {
  public:
    const static int val = Fib<N-1>::val + Fib<N-2>::val;
};

template<> class Fib<2> {
  public:
    const static int val = 1 ;
};

template<> class Fib<1> {
  public:
    const static int val = 1 ;
};

int main()
{
  std::cout << Fib<30>::val << std::endl;
  return 0;
}

På compiletime beregnes det 30'te fibonacci nummer.
(Check evt. selv assembler output :-)
Avatar billede arne_v Ekspert
08. februar 2006 - 04:29 #13
lidt blandet:

man kan faktisk ogsaa lave funktioner med makroer

eksempel:

#define QS(name,type) \
void name##_help(int n1,int n2,type *a) \
{ \
  type tmp; \
  int l = n1; \
  int r = n2; \
  type pivot = a[(n1+n2)/2]; \
  do { \
      while(a[l]<pivot) l++; \
      while(a[r]>pivot) r--; \
      if(l<=r) { \
        tmp = a[l]; \
        a[l] = a[r]; \
        a[r] = tmp; \
        l++; \
        r--; \
      } \
  } while(l<=r); \
  if(n1<r) name##_help(n1,r,a); \
  if(l<n2) name##_help(l,n2,a); \
  return; \
} \
\
void name(int n,type *a) \
{ \
  name##_help(0,n-1,a); \
  return; \
}

Java og C# generics ligner C++ templates lidt men er meget forskellige

C++ templates genererer foerst kode ved instantiering

Java og C# generics kan compiles seperat

det sidste er selvfoelgelig smart, men betyder ogsaa at man ikke kan lave
naer det samme, fordi man er noedt til at erklaere hvilket interface eller
basis klasse typen har for at man kan goere noget med den
Avatar billede mxs Nybegynder
16. december 2008 - 21:15 #14
Jeg fik faktisk meget ud af denne diskussion så jeg vil gerne fordele de 30 point mellem jer, så hvis I vil smide et svar hver så fordeler jeg dem. Tak endnu en gang for jeres svar.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester