Egyszer már próbáltam az ApocalypseKÖZÖS lakóitól segítséget kérni egy problémához, és akkor sikerrel jártam. Szóval most megpróbálom még egyszer.

Egy C++ programot írok, amiben mindenféle komplex számokkal számolok, és ehhez – többek között – egy külső függvénykönyvtár (nevezzük C-LAPACKnak) függvényeit és definícióit használom. A Lapackban létezik egy típusdefiníció a komplex számokra (nagyon egyszerű: egy struct, aminek van egy valós és egy képzetes tagja, mindkettő lebegőpontos szám), nyilván nekem is célszerű ezt használnom. Viszont a kód olvashatósága érdekében szeretném, ha a fordító érteni tudná a c = d jellegű rövidítéseket (ahol c egy ilyen komplex szám, d meg egy lebegőpontos kifejezés), vagyis, hogy ne kelljen se mindig kiírni, hogy c.r = d; c.i = 0, se ne kelljen erre külön valami c = assign_double(d); jellegű utasítást/makrót csinálni.

Ugyanez persze felmerült a szokásos négy alapműveletre is, ott sikerült is megcsinálnom az operator overloadingot pusztán a megfelelő eljárások deklarálásával. Azonban az operator =-t valamiért nem lehet "csak úgy" overloadingolni, mert olyankor egy error: '__CLPK_doublecomplex& operator=(__CLPK_doublecomplex&, double)' must be a nonstatic member function nevű hibát kapok.

A gugli erre azt írta, hogy ennek az a mélyebb oka, hogy az értékadás operátort csakis az osztálydefinícióban lehet megtenni valamiért. Ennek egyrészt vannak egész érthető okai is, másrészt viszont az is nyilvánvaló, hogy miért nem akarok belepiszkálni egy külső függvénykönyvtárba. (Arról nem is beszélve, hogy maga a Lapack nem C++, hanem szimpla C-kód – pontosabban a Lapack FORTRANban íródott és a C-Lapack egy wrapper hozzá –, vagyis nincsenek benne osztályok. Persze nyilván a structok ilyen értelemben osztályként is működnek, de akkor sem akarnék belenyúlni a Lapack headerekbe...)

Nem tudna valaki javasolni nekem valamit, hogy anélkül, hogy bele kéne piszkítanom a Lapack headerekbe, hogyan tudnám mégis megcsinálni, hogy a c = d jellegű értékadás működjön?

Utoljára módosította SAdam 2009.VIII.14 19:10-n
Bejegyzés módosítása | PermaLink
Votes disabled.

Hozzászólások (4)

UPi hozzászólása 2009-08-14 23:26-kor

Csinálj egy osztályt, amelyik leszármazik a lapack-féle struct-ból.


SAdam hozzászólása 2009-08-15 01:32-kor

Az nem jó. Azt ugyanis nem fogják megenni a CLapack függvények (kivéve persze, ha minden egyes hívásnál kiírok valami explicit typecastolást, de akkor ugyanott tartok, hogy megintcsak olvashatatlan a kód – mondom, az egésznek az lenne az értelme, hogy könnyen olvasható maradjon a kód, amit írok).

Valami olyasmi a problémám, hogy míg olyat simán csinálhatok mindenféle osztálydeklarációk nélkül, hogy

 const __CLPK_doublecomplex operator + ( const __CLPK_doublecomplex left, const __CLPK_doublecomplex right ) {
    __CLPK_doublecomplex result;
    result.r = left.r + right.r;
    result.i = left.i + right.i;
    return result;
 }

vagy, hogy

 const __CLPK_doublecomplex operator + ( const __CLPK_doublereal left, const __CLPK_doublecomplex right ) {
    __CLPK_doublecomplex tmp;
    tmp.r = left;
    tmp.i = 0;
    return tmp + right;
 }

(vagyis a komlex + komplex vagy a valós + komplex simán megy), addig a komplex = valós a fenti módon nem működik...

Igazából azért (is) szeretném ezt az egészet megcsinálni rendesen, mert többen is használjuk a Lapack-ot, és az lenne az igazi, ha tudnék gyártani egy olyan header-file-t, amit a többiek utána csak belinkelnek a programjaikba, és az include-ot leszámítva semmi egyebet nem kellene tenniük ahhoz, hogy a c1 + c2, vagy a c = d alakú dolgok helyesen működjenek (miközben a c komplex számokat továbbra is használhatnák a létező Lapack-os függvényeikben).


Wigy hozzászólása 2009-08-15 09:11-kor

Szívesen töprengek veled együtt még a problémán kedd után (addig le leszek vágva a Netről keményen, meglátjuk hogy bírom...) Addig is van egy library, amiből ötleteket nyerhetsz, vagy egyszerűen csak használhatod: http://math.nist.gov/lapack++/

Ha mégis saját megoldást szeretnél készíteni, én a delegációra szavazok.

  1. Készíthetnél egy saját osztályt, ami valami namespace-ben van, és aminek valami rendes neve van (pl. complex).
  2. Ebben az osztályban lenne kb. 1 db adattag: private: __CLPK_doublecomplex impl;
  3. Minden műveletet megírnál a saját osztályodon, használva az impl adattagot.

Az osztályod "érték szemantikájú" legyen, tehát akkor egyenlő 2 példány, ha az impl.re és impl.im egyenlő. Van másoló konstruktora, értékadó operátora, stb. Végül, de nem utolsó sorban, egy konverziós konstruktort és operátort is adnék az osztályhoz, ha van olyan C-s függvény, ami __CLPK_doublecomplex paraméterű és nem szeretnéd becsomagolni C++-ba:

namespace sadam_lapack {

  class complex {
  public:
    explicit complex(__CLPK_doublecomplex a);
    operator __CLPK_doublecomplex() const;
  };

}

SAdam hozzászólása 2009-08-15 13:49-kor

Wow! Köszönöm. Nekiesek (valószínűleg csak hétfőn – hiába, no, kezdek rászokni arra, hogy a hétvége legyen a családé és/vagy a haveroké), aztán leírom, mire jutottam. Minden esetre a Lapack++ elsőre hihetetlenül jó tippnek tűnik, persze még meg kell néznem, hogy van-e OS X-es változata, illetve, hogy le tudom-e fordítani, ha nincs.

Tagek: