Przecinek to taki niepozorny znak, którego grubo ponad 90% zastosowań ogranicza się zapewne do oddzielania parametrów funkcji (czy to w deklaracji, czy to w wywołaniu). Niektóre języki używają też go do separowania indeksów wielowymiarowych tablic, ale do nich C++ akurat nie należy.
Zamiast tego przecinek jest tam operatorem, o czym rzadko się pamięta. Być może dlatego, że ma on najniższy priorytet spośród wszystkich operatorów. Wydaje się też, że domyślne jego działanie (obliczenie wszystkich argumentów, a następnie zwrócenie ostatniego) nie jest specjalnie przydatne – jeśli w ogóle.
Można je jednak zmienić. Tak, tak – operator przecinka można przeciążać, jakkolwiek zaskakujące i przekombinowane by się to wydawało. W rzeczywistości jest on bowiem zwyczajnym operatorem binarnym o łączności lewostronnej i wspomnianym najniższym priorytecie. A przeciążyć można go, pisząc funkcję operator,()
– dokładnie tak samo, jak każdego innego dwuargumentowego operatora.
Do czego może to służyć? Otóż względnie typową sztuczką jest użycie przedefiniowanego przecinka do konstrukcji obiektów złożonych z wielu elementów, np. wektorów lub macierzy. Oto przykład przeciążenia dla standardowej klasy vector
:
Pozwala to na inicjalizację wektora w taki oto nietypowy sposób:
Pierwszy element tego ciągu (pusty wektor) jest konieczny, gdyż w przeciwnym razie użyty zostałby standardowy operator przecinka.
Na pierwszy rzut może to wyglądać efektownie. Pamiętajmy jednak, że przecinek ten pozostaje wciąż przecinkiem, zachowując chociażby swoją główną cechę szczególną, czyli priorytet. W szczególności próba dodania do wektora kolejnych elementów w ten sposób:
zakończy się niezupełnie po naszej myśli…
Mimo to być może warto spróbować wymyślić dla tego operatora jakieś własne, w miarę sensowne zastosowanie. Możliwe, że okaże się on wcale nie tak nieużyteczny, na jakiego zdaje się wyglądać :]
Hahaha świetny pomysł ;>
Pomysł na przeciążenie, nie da się ukryć, oryginalny :D Nigdy nie mogłem wymyślić dla niego jakiegoś sensownego zastosowania, a tu patrz…
Niemniej jednak obawiam się, że w pierwszym przypadku również nie stanie się to, o co Ci chodzi, właśnie przez priorytet przecinka:
Wykonane zostanie przypisanie, potem przeciążony przecinek weźmie PRZEZ WARTOŚĆ jego wynik, doda, po czym zwróci jeszcze inny obiekt. Tzn. wykonane zostałoby itp., gdyby to nie była inicjalizacja- sprawdzałem ten kod na VC++ 2008 EE i się nie kompiluje: error C2059: syntax error : ‘constant’
Oczywiście nawiasy usuwają problem. Obydwie formy działają natomiast, jeśli zamiast przez wartość będziemy przyjmować/zwracać vector przez referencję. Nie zmienia to jednak faktu, że pomysł sam w sobie jest świetny, choć nie wiem, czy się przyjmie :P
Pozdrawiam, mam nadzieję że niczego nie pokręciłem. Nade wszystko jednak gratuluję wyobraźni :D
Faktycznie trochę za bardzo uwierzyłem w zdolności analizatora składniowego w VC++. Teoretycznie powinien bez problemu stwierdzić, że ma doczynienia z deklaracją + inicjalizacją zmiennej, ale widać w praktyce różnie z tym bywa :) (Prawdopodobnie jest to zresztą zachowanie standardowe). Dla porządku poprawiłem już ten przykład.
Natomiast sam pomysł na przeciążanie przecinka nie jest wcale oryginalny; widziałem go przynajmniej w jednej bibliotece matematycznej, tyle że już zapomniałem, w której :)
Cale szczesice w C++0x (o ile kiedykolwiek ten standard bedzie obslugiwany :P) beda juz konstruktury listowe, wiec bedzie mozna zrobic jak bog przykazal:
vector V = { 1, 2, 3 };