Co to jest użycie uniwersalnych nazw znaków w identyfikatorach w C ++

11

C ++ Standard (zauważyłem go w nowym, ale to nie istnieje w C ++ 03) określa uniwersalne imiona postaci, pisane jak \uNNNNi \UNNNNNNNNi reprezentujące znaki z codepoints unicode NNNN/ NNNNNNNN. Jest to przydatne w przypadku literałów łańcuchowych, zwłaszcza że zdefiniowano również literały łańcuchowe UTF-8, UTF-16 i UCS-4. Jednak uniwersalne literały znakowe są również dozwolone w identyfikatorach. Jaka jest motywacja?

Składnia jest oczywiście całkowicie nieczytelna, identyfikatory mogą być zniekształcone dla linkera i nie jest tak, że nie było żadnej standardowej funkcji do pobierania symboli po nazwie. Dlaczego więc ktoś miałby używać identyfikatora z uniwersalnymi literałami znaków?

Edycja: Ponieważ faktycznie istniał już w C ++ 03, dodatkowym pytaniem byłoby, czy rzeczywiście widziałeś kod, który go używał?

Jan Hudec
źródło

Odpowiedzi:

6

AKTUALIZACJA - ta odpowiedź, choć dla mnie i innych wydawała się sensowna, okazuje się być w dużej mierze błędna (i wystarczająco błędna w odniesieniu do intencji, aby faktycznie była po prostu błędna). Ponieważ (jak wskazano w komentarzu AProgrammer) nie można używać LUW poza stałymi ciągami, gdy ten sam znak może być normalnie reprezentowany w podstawowym zestawie znaków. Więc nie używam go do ucieczki słów kluczowych, jak w moim przykładzie; i bez używania go do tworzenia „identyfikatorów”, takich jak 23skiddoucieczka od2. Wydaje mi się, że nadal można go używać do kompatybilności nazw z językami zewnętrznymi, ale tylko wydaje się, że kiedy te nazwy zaczynają się od litery lub znaku rozszerzonego i zawierają tylko litery, cyfry, podkreślenie i znaki rozszerzone - które wydaje się o wiele zbyt restrykcyjne, aby właściwie wspierać ten zamiar. Tak więc musi być tak, że głównym celem jest (jak w odpowiedzi AProgrammera), aby pozwolić tym dodatkowym znakom w identyfikatorach i umożliwić edytorom źródłowym, gdzie te znaki są wyświetlane graficznie, jednocześnie pozwalając, aby plik źródłowy był w postaci zwykłego ASCII.


Programy C ++ mogą wywoływać funkcje napisane w innych językach. Dobrą strategią komitetu normalizacyjnego jest zapewnienie, że C ++ będzie interoperacyjny z innymi językami, które mogą dopuszczać znaki inne niż alfanumeryczne lub znaki Unicode w nazwach funkcji, nawet jeśli takie języki jeszcze nie istnieją. Standard nie musi określać, jak to będzie działać na poziomie linkera itp .; ale dobrze jest mieć określony mechanizm pozwalający na to.

Nie musisz patrzeć w przyszłość, aby zobaczyć zastosowanie. Załóżmy, że mam starą bibliotekę C z funkcją o nazwie catch(lub chronioną lub zmienną) ... i chcę ją wywołać z C ++. I z jakiegokolwiek powodu nie mogę lub nie chcę modyfikować kodu C (nawiasem mówiąc, nieraz miałem do czynienia ze starym kodem C, który używał nazwy funkcji, która stała się słowem kluczowym C ++ ...)

Z nazwami UC mogę napisać to w nagłówku, a następnie po prostu wywołać „catch_func ()”:

extern "C" {
       int catc\u0068( int a, int b );  // C 'catch()' function
}
inline int catch_func( int a, int b ) { return catc\u0068(a,b); }

Jasne, że jest brzydka, ale to nie ma znaczenia, ponieważ jest tylko w jednym miejscu w nagłówku. To samo podejście można zastosować do tworzenia kodów pośredniczących do wywoływania funkcji w innych językach i działa nawet wtedy, gdy nazwy są słowami kluczowymi C ++ lub Unicode, lub zawierają spacje .lub inną interpunkcję

Różne inne języki mają urządzenia umożliwiające tworzenie identyfikatorów, które nie są zgodne z ogólnym wzorcem; na przykład w Verilogu, \abcdjest równoważny identyfikator do abcd, ale \whilei \23skidooa \44.e2są zbyt identyfikatory, które powinny prefiks backslash być postrzegane jako takie. Ze względu na sposób korzystania z Verilog ważne jest, aby w ogóle dopuszczać dowolne nazwy, jeśli dotyczą one interfejsów zewnętrznych.

greggo
źródło
Ciekawy przypadek użycia. Chociaż podejrzewam (gdy jest to możliwe), byłoby lepiej napisać mały plik C, aby przetłumaczyć nazwę (i dzięki temu można użyć identyfikatora C ++) i wywołać funkcję C ++ w C ++.
Thomas Eding
1
Nie można tego napisać z dwóch powodów: pierwszy LUW poza ciągiem znaków i literałami znaków nie może odnosić się do znaku w zestawach podstawowych bez zniekształcania programu, po drugie, jeśli ta klauzula nie była obecna, LUW są obsługiwane w fazie 1 tłumaczenia i dlatego nie byłoby różnicy w obsłudze między LUW odnoszącym się do znaku w zestawie podstawowym a samym znakiem.
AProgrammer
4

Pozwala systemowi pozwalającemu na znaki Unicode w identyfikatorze eksportować źródło w formacie kompatybilnym z dowolnym standardowym kompilatorem zgodnym. IE jest to sposób na zakodowanie Unicode na podstawowym zestawie znaków (mniej więcej tak, jak w przypadku wiadomości e-mail używany jest wydruk z cytatem, systemy, które lepiej wiedzą, są w stanie wykonać lepszą pracę, inne systemy nadal działają).

AProgrammer
źródło
2

Ktoś może chcieć utworzyć identyfikator za pomocą znaku języka obcego, którego nie można wprowadzić na klawiaturze lub urządzeniu wejściowym. Alternatywnie identyfikator może zawierać znak, którego nie można wydrukować przy użyciu czcionek lub możliwości wydruku urządzenia, ale IDE chce pokazać dokładną reprezentację.

akton
źródło
4
W pierwszym przypadku identyfikator nie wyglądałby tak, jakby miał ten znak, więc kod byłby nieczytelny, a identyfikator nie ma tak naprawdę znaczenia dla maszyny. Po drugie, reprezentacja w IDE jest całkowicie odrębnym problemem.
Jan Hudec
1

C ++ wymaga, aby rzeczywiste znaki rozszerzone występujące dosłownie w źródle zachowywały się identycznie jak uniwersalne nazwy znaków. Zezwalanie na uniwersalne nazwy znaków w identyfikatorach pozwala programistom na stosowanie rozszerzonych znaków w identyfikatorach.

bames53
źródło
Obsługiwane są rzeczywiste znaki rozszerzone, które muszą zachowywać się jak odpowiadające im znaki uniwersalne. Ale nie trzeba ich wspierać.
Jan Hudec
1
To prawda, ale w pewnym sensie nie ma sensu, że jeśli komitet chce sprecyzować, że implementacje obsługujące znaki rozszerzone powinny obsługiwać używanie tych znaków w identyfikatorach, to wymaga, aby UCN były dozwolone w identyfikatorach. Tj. UCN są dozwolone w identyfikatorach, niekoniecznie dlatego, że jest to tak czytelne i wszyscy uwielbiają ręcznie kodować nazwy w systemie szesnastkowym, ale ponieważ jeśli specyfikacja chce zezwolić na stosowanie rozszerzonych znaków w identyfikatorach, robi to poprzez określenie, że UCN są dozwolone w identyfikatorach.
bames53