Na pierwszy rzut oka wydaje się, że jest to prosty cukier syntaktyczny.
Ale patrząc głębiej, widzimy, że jest to coś więcej niż cukier składniowy, ponieważ rozszerza możliwości użytkownika C ++ o tworzenie typów zdefiniowanych przez użytkownika, które zachowują się dokładnie tak, jak odrębne typy wbudowane. W tym przypadku ten mały „bonus” jest bardzo interesującym dodatkiem C ++ 11 do C ++.
Czy naprawdę potrzebujemy tego w C ++?
Widzę kilka zastosowań w kodzie, który napisałem w ostatnich latach, ale to, że nie użyłem go w C ++, nie oznacza, że nie jest on interesujący dla innego programisty C ++ .
Użyliśmy w C ++ (i chyba w C) literałów zdefiniowanych przez kompilator, aby wpisać liczby całkowite jako krótkie lub długie liczby całkowite, liczby rzeczywiste jako zmiennoprzecinkowe lub podwójne (lub nawet długie podwójne), a ciągi znaków jako zwykłe lub szerokie znaki .
W C ++ mieliśmy możliwość tworzenia własnych typów (tj. Klas), potencjalnie bez narzutów (inlining itp.). Mieliśmy możliwość dodawania operatorów do ich typów, aby zachowywały się jak podobne typy wbudowane, co umożliwia programistom C ++ używanie macierzy i liczb zespolonych tak naturalnie, jak by to było, gdyby zostały dodane do samego języka. Możemy nawet dodać operatory rzutowania (co zwykle jest złym pomysłem, ale czasami jest to właściwe rozwiązanie).
Wciąż brakowało nam jednej rzeczy, aby typy użytkowników zachowywały się jak typy wbudowane: literały zdefiniowane przez użytkownika.
Więc myślę, że jest to naturalna ewolucja języka, ale aby być jak najbardziej kompletnym: „ Jeśli chcesz utworzyć typ i chcesz, aby zachowywał się jak typy wbudowane, oto narzędzia. .. ”
Wydaje mi się, że jest to bardzo podobne do decyzji .NET, aby uczynić każdy element pierwotny strukturą, w tym wartości logiczne, liczby całkowite itp., I wszystkie struktury pochodzą od Object. Już sama ta decyzja stawia .NET daleko poza zasięgiem Javy podczas pracy z prymitywami, bez względu na to, jak wiele hacków związanych z boksowaniem / rozpakowywaniem Java doda do swojej specyfikacji.
Czy naprawdę potrzebujesz tego w C ++?
To pytanie jest dla CIEBIE odpowiedzieć. Nie Bjarne Stroustrup. Nie Herb Sutter. Nie jest członkiem komitetu standardowego C ++. Dlatego masz wybór w C ++ i nie ograniczą one użytecznej notacji do samych typów wbudowanych.
Jeżeli ty potrzebujesz, to jest to dodatek mile widziane. Jeśli ty nie, dobrze ... Nie używaj go. Nic cię to nie kosztuje.
Witamy w C ++, języku, w którym funkcje są opcjonalne.
Nadęty??? Pokaż mi swoje kompleksy !!!
Istnieje różnica między nadętym a złożonym (gra słów zamierzona).
Jak pokazał Niels w Jakie nowe możliwości dodają literały zdefiniowane przez użytkownika do C ++? , możliwość zapisania liczby zespolonej jest jedną z dwóch funkcji dodanych „ostatnio” do C i C ++:
// C89:
MyComplex z1 = { 1, 2 } ;
// C99: You'll note I is a macro, which can lead
// to very interesting situations...
double complex z1 = 1 + 2*I;
// C++:
std::complex<double> z1(1, 2) ;
// C++11: You'll note that "i" won't ever bother
// you elsewhere
std::complex<double> z1 = 1 + 2_i ;
Teraz zarówno typ „podwójnie złożony” w C99, jak i „std :: złożony” w C ++ mogą być mnożone, dodawane, odejmowane itp. Przy użyciu przeciążania operatorów.
Ale w C99 po prostu dodali inny typ jako typ wbudowany i wbudowaną obsługę przeciążania operatora. Dodali też kolejną wbudowaną funkcję dosłowną.
W C ++ po prostu wykorzystali istniejące cechy języka, zobaczyli, że funkcja dosłowna była naturalną ewolucją języka, i w ten sposób ją dodali.
W C, jeśli potrzebujesz tego samego ulepszenia notacji dla innego typu, nie masz szczęścia, dopóki nie zaczniesz lobbować, aby dodać funkcje fal kwantowych (lub punkty 3D, lub jakikolwiek podstawowy typ, którego używasz w swojej dziedzinie) do Standard C jako typ wbudowany kończy się sukcesem.
W C ++ 11 możesz to zrobić sam:
Point p = 25_x + 13_y + 3_z ; // 3D point
Czy jest nadęty? Nie , istnieje taka potrzeba, o czym świadczy, jak kompleksy C i C ++ potrzebują sposobu reprezentowania ich dosłownych wartości zespolonych.
Czy jest źle zaprojektowany? Nie , została zaprojektowana jak każda inna funkcja C ++, z myślą o rozszerzalności.
Czy jest to tylko do celów notacji? Nie , ponieważ może nawet dodać bezpieczeństwo typów do twojego kodu.
Na przykład, wyobraźmy sobie kod zorientowany na CSS:
css::Font::Size p0 = 12_pt ; // Ok
css::Font::Size p1 = 50_percent ; // Ok
css::Font::Size p2 = 15_px ; // Ok
css::Font::Size p3 = 10_em ; // Ok
css::Font::Size p4 = 15 ; // ERROR : Won't compile !
Wówczas bardzo łatwo jest wymusić mocne wpisywanie w przypisaniu wartości.
Czy jest niebezpieczny?
Dobre pytanie. Czy te funkcje mogą mieć przestrzeń nazw? Jeśli tak, to Jackpot!
W każdym razie, jak wszystko, możesz się zabić, jeśli narzędzie zostanie niewłaściwie użyte . C jest potężny i możesz odstrzelić sobie głowę, jeśli niewłaściwie użyjesz pistoletu C. C ++ ma pistolet C, ale także skalpel, paralizator i inne narzędzie, które znajdziesz w zestawie narzędzi. Możesz niewłaściwie użyć skalpela i wykrwawić się na śmierć. Lub możesz zbudować bardzo elegancki i solidny kod.
Tak więc, jak każda funkcja C ++, czy naprawdę jej potrzebujesz? Jest to pytanie, na które musisz odpowiedzieć, zanim użyjesz go w C ++. Jeśli tego nie zrobisz, nic Cię to nie kosztuje. Ale jeśli naprawdę tego potrzebujesz, język cię nie zawiedzie.
Przykład daty?
Wydaje mi się, że twoim błędem jest to, że mieszasz operatory:
1974/01/06AD
^ ^ ^
Nie można tego uniknąć, ponieważ / będąc operatorem, kompilator musi to zinterpretować. I AFAIK, to dobra rzecz.
Aby znaleźć rozwiązanie twojego problemu, napisałbym dosłownie w inny sposób. Na przykład:
"1974-01-06"_AD ; // ISO-like notation
"06/01/1974"_AD ; // french-date-like notation
"jan 06 1974"_AD ; // US-date-like notation
19740106_AD ; // integer-date-like notation
Osobiście wybrałbym liczbę całkowitą i daty ISO, ale to zależy od TWOICH potrzeb. I o to właśnie chodzi w umożliwieniu użytkownikowi definiowania własnych nazw literałów.