Mert a tömbözés csak csinizett pointer-aritmetika, az meg definíció szerint így működik.
When an expression that has integral type is added to or subtracted from a pointer, the result has the type of the pointer operand. If the pointer operand points to an element of an array object, and the array is large enough, the result points to an element offset from the original element such that the difference of the subscripts of the resulting and original array elements equals the integral expression. In other words, if the expression P points to the i-th element of an array object, the expressions (P)+N (equivalently, N+(P)) and (P)-N (where N has the value n) point to, respectively, the i + n-th and i − n-th elements of the array object, provided they exist.
(Ha már itt tartunk, a harmadik sem egy ad-hoc alternatív jelölés, hanem egy digráf, béna karakterkészletek meg terminálok számára: Digraphs and trigraphs - Wikipedia, the free encyclopedia
Egyszer jót szívtam velük, mert egy rakás kérdőjellel kellett match-elnem valamit, és csak a lefordult kódot szemrevételezve tűnt fel, hogy az eredeti kérdőjel-sorozatok lerövidültek)
Regebben minden c++ hirhez beirtad, hogy a C++ milyen lassan fordul, es neked mennyivel jobb delphivel dolgozni. Most mindenhova azt fogod beirni, a D szintaxisa mennyivel jobb, es mennyivel jobb neked azzal dolgozni?
Van egy lényeges különbség: "Struct is a value type while class is a reference type". - Ha még mindíg a C#-ról van szó. Gyakran nem észrevehető, csak több vagy kevesebb boxing/unboxing művelet a háttérben.
Itt még szerencse, hogy csak ennyi a különbség C#-ban még ennél is cifrább a struct és a class fogalmak. Állásinterjún szokták kérdezni, hogy akkor a struct öröklés hogy is van. Én erre csak azt szoktam válaszolni, hogy nálatok ugye nem szokás örökölni struct-ot, mert akkor abba is hagyhatjuk az interjút.
Más nyelveken is lehet nyakatekerten programozni, ezért kellenek a kódolási konvenciók, meg szerintem attól is szakember valaki, hogy olvashatóan kódol.
Öröklődésnél is van különbség, osztálynál ott is private az alapértelmezett, struktúránál pedig public. Illetve a class-t lehet használni template<class> -nál is amíg a structot nem.
Mondjuk amikor a nyelvet tervezték az volt a cél, hogy senki se ismerje az összes nyelvi elemet, ezért 1 dolog legalább 3 célra használható, és 1 célra legalább 3 használható dolog van.
Definíció szerint a struktúra (struct), olyan osztály, melynek tagjai alapértelmezés szerint nyilvánosak. Vagyis a
struct s { ...
egyszerûen rövidítése az alábbinak:
class s { public: ...
A választott stílust csak a körülmények és az egyéni ízlés határozza meg. Én általában azokat az osztályokat adom meg struct-ként, amelyekben minden tag nyilvános. Ezekre az osztályokra úgy gondolok, mint amik nem igazi típusok, csak adatszerkezetek. A konstruktorok és lekérdezõ függvények nagyon hasznosak lehetnek a struktúrák számára is, de inkább csak jelölésbeli könnyebbséget jelentenek, mintsem a típus tulajdonságait garantálják
A struct pl. nagyon nem azonos a class-szal (még akkor sem, ha lehet bele tagfüggvényt írni)
Nem szoktam én sem keresztben használni őket, de tudtommal lehet. Ha találomra kiválasztott class kulcsszavakat lecserélsz struct-ra, a futó kód szempontjából nem történik semmi.
- az && operatornak sikerult egy uj ertelmet talalni, tehat mostantol mar a tokenizer nem tudja kapasbol megmondani, hogy az a bool and, hanem tovabbi vizsgalat szukseges.
Ha ez megnyugtat, eddig sem tudta.
// mindenhol mast jelent
template<typename T>
class Type_wrapper {
public:
Type_wrapper(T&&);
template<typename U>
void assign(U&&);
template<typename U>
void assign(const U&&);
T get()&&;
};
// ezek is aranyosak
using int_ref = int&;
int_ref& a = ...;
int_ref&& b = ...;
auto&& x =...;
const auto&& y = ...;
bool addable(T)() {
return __traits(compiles, (T t) { return t + t; });
}
//Ekkor a hasznalat a kovetkezo:
T add(T)(T a, T b)
if(addable!T)
{
return a + b;
}
A hibauzenet pedig:
VectorLogViewer.d(56): Error: template VectorLogViewer.MyWin.doCreate.add cannot deduce function from argument types !()(string, string), candidates are:
VectorLogViewer.d(49): VectorLogViewer.MyWin.doCreate.add(T)(T a, T b) if(addable!T)
Kozben most en is csak tanulok. De ebben az eletemben szerintem annyira perverz mar nem leszek, hogy megertsem a Cpp templateokat :D Nemreg neztem youtubeon egy eloadast, ami egy idezettel inditott: "Nobody understands Cpp templates", kivetelek nyilvan vannak, de szakadtam rajta )
C++-os hibaüzenetek is elég sokat fejlődtek template-k terén.
pl a konkrét példádnál maradva:
cpp_check.cpp: In instantiation of 'T add(T, T) [with T = Foo]':
cpp_check.cpp:15:18: required from here
cpp_check.cpp:9:11: error: no match for 'operator+' (operand types are 'Foo' and 'Foo')
return a + b;
~~^~~
(Persze még kihányt jónéhány sor candidate-t, de ez a hiba kimenet első 5 sora. Egyértelmű)
Itt jön a concept, ami egy új absztrakciós szintet vezet a template-k világába. Konkrét példa:
template <class T>
concept bool Addable = requires(T x) { x + x; };
template <Addable T>
T add(T a, T b)
{
return a + b;
}
(Szerintem nem érthetetlenebb a 'D'-s megfelelőjénél, sőt..)
Az eredeti template-ben a 'typename'/'class'-t lecserélve a megfelelő conceptre (tehát egyetlen szót átírva) sokkal több értelmet adtunk az adott függvénynek.
A hibaüzenetek pedig még egyértelműbbek, mert nem jönnek a candidate-s bloating, meg a többi..
cpp_check.cpp: In function 'int main()':
cpp_check.cpp:18:18: error: cannot call function 'T add(T, T) [with T = Foo]'
add(Foo(), Foo());
^
cpp_check.cpp:10:3: note: constraints not satisfied
T add(T a, T b)
^~~
cpp_check.cpp:7:14: note: within 'template<class T> concept const bool Addable<T> [with T = Foo]'
concept bool Addable = requires(T x) { x + x; };
^~~~~~~
cpp_check.cpp:7:14: note: with 'Foo x'
cpp_check.cpp:7:14: note: the required expression '(x + x)' would be ill-formed
Es jobban megnezve az altalad mutatott peldakat, a && az lehet reference of reference of is, ááá
Nem, referenciákra nem lehet referenciát állítani. (Nincs többszörös indirekció, mint a pointereknél, de értelme se lenne, mert a referencia egész élete alatt ugyanoda mutat.) Az && típusok esetén rvalue reference-et jelent, ami egy másik cifra dolog.
(Hozzáteszem, a nyelvet én sem használom, csak egyfajta perverz szórakozásból igyekszem megérteni. Nem tudom, mennyire boldogulnék vele a gyakorlatban, főleg hosszú évek javás gondolkodásmódja után.)
Itt egy konkret pelda:
- A stringek osszefuzesere a ~ operator valo, nem a +, ezert nem sikeres stringre a static assert.
- A __traits() maga a reflection, most eppen csak lefordithatosag tesztelesere van hasznalva. De ha nem eleg szep, lehetne csinalni belole egy macrot: canCompileOperator(t, "+") alakban.
A < > templatekre valo bevezetesebol még regen a Delphiben is csak bennehagytak egy bugot.
> >> >= = Ezeknek a feldolgozasahoz mar kulon mesterseges intelligencia kell. :D
A D nyelvnek van az a filozofiaja, hogy nem lehetnek benne tobbertelmu tokenek. Emiatt még ha semmit sem tudsz a nyelvrol, csak annyit, hogy hogyan szedd ki a kommenteket es a stringeket, a [] {} () jelek segitsegevel mar fel is epitheted a program fa strukturajat (a makrokkal egyetemben, mert azok definialasanal es hasznalatanal is ezek a jelek tagolnak.). Ez a konkret contrakt dolog pedig ott ugy van megoldva, hogy forditasi idoben barmilyen D expression kiertekelheto (pl static if-el vagy static assert-tel), amelyik nem hivatkozik futas ideju adatra, tehat akár a tipusokkal dolgozo muveletek (fullos reflection), akár az ezekbol kepzett D functok is dobhatjak a forditasi ideju errort/warningot, hogy "sorry, ez a template parameter nem megfelelo".
Es jobban megnezve az altalad mutatott peldakat, a && az lehet reference of reference of is, ááá -> (Nincs, harag de ezzel a nyelvvel én még egyszer nem akarok talalkozni, lol. Jo lesz nekem a D, sajat FW-vel meg sajat IDE-vel es one man projectekkel :D Mikozben tiszteletben tartom, hogy sokaknak a munkaltatoja hatarozza meg, hogy miben, hogyan dolgozzon.)
Melyik példakódban volt ilyen? Bár csak átfutottam a szöveget, nekem mindenhol úgy tűnt, hogy az && az továbbra is bool and és semmi más. A concept egy olyan valami, ami fordítási időben bool-ra értékelődik ki (akkor és csak akkor true-ra, ha a megadott típus(ok) megfelel(nek) a koncepciónak), így nyilván ha valamit több conceptre is ellenőrizni akarsz, arra az && operátor való.
Vegul ezt az egeszet sikerult function palameterlistakent alcazni.
Három szintaxisa van, abból csak a legegyszerűbb "álcáz" bármit paraméterlistának. Ott viszont direkt az volt a cél, hogy a concept ne nézzen ki különbözőnek a "mezei" típusoktól, mivel a célja ugyanaz (megkövetelni, hogy a kapott paraméter típusa bizonyos megszorításoknak megfeleljen).
Ha neked nem tetszik az a megfogalmazás, hogy:
void sort(Sortable& foo);
akkor meg van engedve, hogy helyette ezzel koptasd a billentyűzetedet:
Nekem a peldakod megtekintese utan a kovetkezo dolgok tetszettek nagyon:
- az && operatornak sikerult egy uj ertelmet talalni, tehat mostantol mar a tokenizer nem tudja kapasbol megmondani, hogy az a bool and, hanem tovabbi vizsgalat szukseges. Nagyobb teljesitmenyigeny, bonyolultabb fordito, megnovekedett villanyszamla -> novekvo GDP.
- Vegul ezt az egeszet sikerult function palameterlistakent alcazni. Egyszeruen nem talalok szavakat. ;D
szeretem a duplikált featúrákat, mint referencia/pointer, array/vector, struct/class, char []/string, NULL/nullptr_t, FILE/iostreams, makró/template etc
Mondjuk a felsoroltak közül a fele csak szintaxis szintjén (vagy ott sem) csereszabatos. A struct pl. nagyon nem azonos a class-szal (még akkor sem, ha lehet bele tagfüggvényt írni), aki a char[]-t és a string-et keveri, az biztosan képes egy sor egyéb aljasságra is, és a makrók és template-ek is teljesen különböző célt szolgálnak.
Milyen problémámat? Nincs problémám, épp azt mondom, hogy szeretem a duplikált featúrákat, mint referencia/pointer, array/vector, struct/class, char []/string, NULL/nullptr_t, FILE/iostreams, makró/template etc