fordításidejű kulcselosztás

Fórumok

Sziasztok!

Azt szeretném elérni, hogy több osztály ugyanazon nevű statikus adattagjának fordítás időben adjunk egymástól diszjunkt értékeket. Tehát :


#include <iostream>

class A { 
  public : static const int MSGID =  ?
};
class B { 
  public : static const int MSGID =  ?
};
class C { 
  public : static const int MSGID =  ?
};

int main()
{
  std::cout << A::MSGID << std::endl;
  std::cout << B::MSGID << std::endl;
  std::cout << C::MSGID << std::endl;
  return 0;
}

Mit javasolnátok a ? helyére, ha a kimenetben pl


1
2
3

-t szeretnék látni?

Vagy másképpen fogalmazva milyen metaprogram ekvivalens a következővel:


int next()
{
  static int cnt = 1;
  return cnt++;
};

class A {  public :  static int MSGID; };
int A::MSGID = next();
...

Nyilván valamiféle

 MSGID = generator< T >::next; 

-ben kell gondolkodni, legalább 1 template paraméter kell.
Természetesen szám paraméterrel meg lehet oldani, de annak nincs értelme, hisz akkor már bele is égethetnénk a kódba az értékeket.

Csak ötleteket várok!

Hozzászólások

Nem a fordítási idő a lényeges, amit linkeltél az szimplán mást csinál.

Az azonos osztályba tartozó objektumok létrehozásait számolja.
verkri viszont az osztályokhoz szeretne egy azonosító számot.

"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee."
-- Ted Ts'o

az egy pattern... nem csak arra lehet hasznalni...

raadasul ha egy osztalyvaltozod, ami nem konstans, es azzal szamolod az objektumokat,
a leszarmazattban (ami ugye ebbol a template-bol szarmazik es sajat magat adja at sablonparameterkent) beteszel egy peldanyvaltozot, aminek ertekul adod az osztalyvaltozo akt. erteket(tkeppen lemented a szamlalo allapotat a peldany szamara letrehozaskor), akkor az is lehet azonosito...

de ez futasi ido, nem forditasi

Nálam a következő program azt valósítja meg, amit szerettél volna:


#include iostream  // kacsacsőrök eltávolítva. a kijelezhetőség végett

class A { 
  public : static const int MSGID =  1;
};
class B { 
  public : static const int MSGID =  2;
};
class C { 
  public : static const int MSGID =  3;
};

int main()
{
  std::cout << A::MSGID << std::endl;
  std::cout << B::MSGID << std::endl;
  std::cout << C::MSGID << std::endl;
  return 0;
}

g++ -val fordítottam.

Konkretan a &lt; es &gt; HTML tagek. Amugy telleg jo lenne, ha trey csinalna valamit, a regi HUP-on ez ment. En fel tudnam aldozni a kodon beluli html formazas lehetoseget, ha ezzel visszaallna a regi mukodes.
--


()=() Ki oda vagyik,
('Y') hol szall a galamb
C . C elszalasztja a
()_() kincset itt alant.

Eleve nem értem minek vannak engedélyezett HTML tag-ek.
Max arra jók, hogy szétcsapják az oldalt, ha a kedves user nem zárta le őket...
Közben meg vannak a BBCode-ok is, ahol ez a probléma nem áll fent.

"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee."
-- Ted Ts'o

Ha nem a deklarációban adod meg az MSGID-et, akkor megadhatod értéknek egy fv kimenetét:


const int C::MSGID = Counter::inc();

Ha ez a statikus fv lökdös egy statikus számlálót, mindig más értéket kapsz.

Azt mondjuk érdemes megjegyezni, hogy a statikus adattagok kezdeti értékadásának sorrendjét semmi sem garantálja, attól függően, hogy milyen sorrendben linkelsz más más eredményt kaphatsz...

(Az persze garantált, hogy inicializálva lesz mielőtt először hozzáférsz.)

"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee."
-- Ted Ts'o

Először én is valami template-es megoldáson törtem a fejem, de félek az nem lehetséges...

"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee."
-- Ted Ts'o

template-nek template:


#include <iostream>

#include <boost/mpl/vector.hpp>
#include <boost/mpl/find.hpp>

class A;
class B;
class C;

typedef boost::mpl::vector<A,B,C> classes;

class A { 
public: 
	static const int MSGID = boost::mpl::find<classes,A>::type::pos::value;
};
class B { 
public: 
	static const int MSGID = boost::mpl::find<classes,B>::type::pos::value;
};
class C { 
public: 
	static const int MSGID = boost::mpl::find<classes,C>::type::pos::value;
};

int main()
{
  std::cout << A::MSGID << std::endl;
  std::cout << B::MSGID << std::endl;
  std::cout << C::MSGID << std::endl;
  return 0;
}

"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee."
-- Ted Ts'o

Arra gondolok, hogy a kifejezésekből egy végrehajtási gráf épül, amiben egy-egy kifejezésnek mindig konstans az értéke. Tehát, ha két helyen szerepel ugyanaz a kifejezés, akkor ez a kettő ugyanazt jelenti, így generátor nem használható, vagyis minden msgid definíció valamiben el kell hogy térjen.

A legegyszerűbb ilyenkor, ha az őt tartalmazó típus az, amiben eltér a definíció, amihez érdemes makrót írni, aminek a paramétere az osztály neve. Szükség van még egy osztályok -> int leképezésre, amihez vagy specializációkat kell írni explicit hozzárendeléssel, vagy ha nem akarsz számokat írni, akkor egy listában felsorolhatod, ld. tr3w módszerét.

Ezek egy fájlban vannak, ugye?

__LINE__ Integer value representing the current line in the source code file being compiled.

KisKresz

Egy barátom hívta fel rá a figylemem:

"VC++-on es talan GCC-n is van __COUNTER__

egyebkent http://lists.boost.org/Archives/boost/2002/10/38298.php"

Az első gondolom csak fordítási egységenként működik.

A második is, plusz még sérti a C++ szabványt is. De ennek ellenére sok fordítóval lefordul.

"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee."
-- Ted Ts'o


// alma.cpp

#define NEXT2(x) __FILE__ ":" #x
#define NEXT1(x) NEXT2(x)
#define NEXT NEXT1(__LINE__)

struct A {
  static const char id[];
};

struct B {
  static const char id[];
};

struct C {
  static const char id[];
};

const char A::id[] = NEXT;
const char B::id[] = NEXT;
const char C::id[] = NEXT;

const int-ről volt szó...

Ha meg hash fv-t rendelsz hozzá akkor máris fordításidejű.

De akkor már itt egy hasonló:



class A { 
public: 
	static const char* MSGID;
};
const char* A::MSGID = typeid(A).name();

class B { 
public: 
	static const char* MSGID;
};
const char* B::MSGID = typeid(B).name();

class C { 
public: 
	static const char* MSGID;
};                   
const char* C::MSGID = typeid(C).name();


int main()
{
  std::cout << A::MSGID << std::endl;
  std::cout << B::MSGID << std::endl;
  std::cout << C::MSGID << std::endl;
  return 0;
}

"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee."
-- Ted Ts'o


#include

class A;
class B;
class C;

template
struct What {
enum { RET = 1 };
};

template <>
struct What {
enum { RET = 1 };
};

template <>
struct What {
enum { RET = 2 };
};

template <>
struct What {
enum { RET = 3 };
};

class A {
public:
static const int MSGID = What::RET;
};

class B {
public:
static const int MSGID = What::RET;
};

class C {
public:
static const int MSGID = What::RET;
};

int main()
{
std::cout << A::MSGID << std::endl;
std::cout << B::MSGID << std::endl;
std::cout << C::MSGID << std::endl;
return 0;
}

Eleg, ha egy c++ fileon belul egyedi ? Vagy globalisan egyedi kell ?
Ha globalisn egydi kell, akkor javasolhatom a "sajat elfordito" lepest, vagyis c++ forgatas elott attolni egy csoda scripten minden filet.
Ha filen beluli akkor a __LINE__ macro sem rossz.
szerk:
Tovabb gondolva 100000 sornal csak nem hosszabb a kodod/c++ file es 20000 nel tobb filod nem igen lessz , tehat minden fileban eleg ennek kulonbozo tobszoroset hozza adni.

Amit nem lehet megirni assemblyben, azt nem lehet megirni.

A gond szerintem abban keresendo, hogy a c++ nem igazan tudja, hogy mik ezek a tagok, akkor sem, ha alaptipusok. A preprocesszor az ugye inkabb statikus cserekre van szakosodva (egy mini sed), a fordito meg mar nem nyulkalhat a preprocesszalt kodhoz ilyen valtoztatasokkal (o csak a garantalt operatorokat es konstruktor/destruktorokat generalhatja le). Innentol nem tudom, hova gondoltad beilleszteni az ertekadas folyamatat, foleg kulso, egyedileg eldontott valtozoertekadast. Mert ha azt mondom, hogy legyen a __LINE__ erteke, elkuldesz a rak farkara, mert konstans. __FILE__, _FUNCINFO__ - megint konstans.

Gondold at, hogy mi a feladat, mert szinte biztos, hogy nem jofele keresgelsz. Miert kell neked FORDITASI idoben ertekeket kapnod? Miert nem eleg a futasideju? Mondd el, mi a feladat, mert akkor talan segiteni is tudunk.

Szerk: ez a topicnyitonak akart menni... :S
--


()=() Ki oda vagyik,
('Y') hol szall a galamb
C . C elszalasztja a
()_() kincset itt alant.