fordításidejű kulcselosztás

 ( verkri | 2009. január 6., kedd - 21:35 )

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 

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ás megjelenítési lehetőségek

A választott hozzászólás megjelenítési mód a „Beállítás” gombbal rögzíthető.

Csak én nem látom ez miért segít?

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

nem, en is latom :)
nem figyeltem, hogy static const-nak kellene lennie az azonositonak
ez csak akkor lenne jo, ha nem forditasi idoben kene erteket adni...

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

Nyilván nem csak arra... Sőt elsősorban nem arra szokták.

Ettől még köze sincs a jelenlegi problémához...

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

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.

neeee... ilyeneket ne.

"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."

Érted ?

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

less than és greater than segíthet.
--
unix -- több, mint kód. filozófia.
Life is feudal

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

Azért mert nagyon durván bugos a Drupal [url] kezelése.
Tulajdonképpen Wikipédia linkeket nem fogad el (illetve nagyon kis százalékban).

--
Elder Scrolls

Nekem eddig még csak a zárójeleket nem szerette...

"...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

ez nem fordításidejű.

Nem.

Viszont működik. :)

"...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

A template metaprogramozás Turing-teljes, így _MINDEN_ ami kiszámítható, megvalósítható. Csak kérdés, hogy hogyan.:D

Funkcionális nyelvekben alkalmazható technikákat használva. A generátor sajnos nem ilyen, és kb. csak úgy lehet ahogy tr3w írta.

A generator< T >-re gondolsz, amit írtam ? Azt csak példának írtam, természetesen ettől el lehet térni. És mit értesz metaprogramozásban funcionális technikák alatt ?

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.

Ha jól emlékszem ezt hívtuk úgy, hogy funkcionális nyelvekben nincs destruktív értékadás...

Kivéve, ha hülyeségeket beszélek...

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

Ezek egy fájlban vannak, ugye?

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

KisKresz

Ez szellemes:)

Hihi, nem rossz, nem rossz. Egy pontot megér. Viszont van egy rossz hírem : több fájlban is lehetnek ( legalábbis jó lenne támogatni ezt is ).

Az a baj, hogy különböző fájlok fordítása egymástól független, így nem látom, hogy ezt meg lehetne oldani fordítási időben.

KisKresz

Egy alkalmazáshoz tartozó, külön fájlok ( header-k ). Nem voltam egyértelmű, bocs.

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

subscribe

// 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

A kód fele nem látszik, de abból amit látni ez mindössze a kézzel megadott konstans bonyorultabb esete...

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

Legyszives 5-10 sorosnal nagyobb kodok eseteben pastebin, koszi.
--

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

Tényleg jobb pastebinnel, csak most olvastam újra a hozzászólást :)

http://pastebin.com/m2479a21f

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.

+1 a forditas elotti sajat preprocesszor szkriptre.

De ha hajlando vagy minden fajl elejere beirni egy egyedi szamot akkor tedd azt:

#define FILE_ID 1

...
int id = __LINE__ * 10000 + FILE_ID;

Ha globális kell, akkor arra is van megoldás:


static int a, b, c;

class A {
public:
static int ID;
};

class B { ... };
class C { ... };

A::ID = (int)&a;
B::ID = (int)&b;
C::ID = (int)&c;

Ez egyedi ID-t eredényez.

Mondok jobbat, nem is kell az a, b, c valtozó.


A::ID = (int)&A::ID;
B::ID = (int)&B::ID;
C::ID = (int)&C::ID;

Legalábbis C-ben ez a kód fordult szépen:

static int a = (int)&a;

Gondolom c++-ban is megy.

Szellemes, de ez is futasideju.

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.