Wycofanie statycznego słowa kluczowego… koniec?

89

W C ++ możliwe jest użycie staticsłowa kluczowego w jednostce translacyjnej, aby wpłynąć na widoczność symbolu (deklaracja zmiennej lub funkcji).

W n3092 to zostało wycofane:

Załącznik D.2 [depr.static]
Używanie słowa kluczowego static jest przestarzałe podczas deklarowania obiektów w zakresie przestrzeni nazw (patrz 3.3.6).

W n3225 zostało to usunięte.

Tylko artykuł udało mi się znaleźć to nieco nieformalny.

Podkreśla jednak, że ze względu na zgodność z C (i możliwość kompilowania programów w C jako C ++) wycofanie się jest denerwujące. Jednak kompilowanie programu w języku C bezpośrednio jako C ++ może już być frustrujące, więc nie jestem pewien, czy wymaga to rozważenia.

Czy ktoś wie, dlaczego został zmieniony?

Matthieu M.
źródło
3
Deklarujesz obiekty w zakresie przestrzeni nazw w C?
Etienne de Martel
heh, thx, znalazłem, gdzie go zdobyć. Próbowałem usunąć komentarz, ale mnie tam pokonałeś.
Edward Strange
Pytanie wynikło ze stackoverflow.com/questions/4725204/ ...
Fred Nurk
1
Daje to również Komisji C ++ możliwość wycofania czegoś z kolejnej wersji Standardu :-)
James McNellis,

Odpowiedzi:

75

W C ++ Standard Core Language Defect Reports and Accepted Issues, Revision 94 under 1012. Undeprecating static `` zauważają:

Chociaż 7.3.1.1 [namespace.unnamed] stwierdza, że ​​użycie słowa kluczowego static do deklarowania zmiennych w zakresie przestrzeni nazw jest przestarzałe, ponieważ nienazwana przestrzeń nazw stanowi lepszą alternatywę, jest mało prawdopodobne, że funkcja zostanie usunięta w dowolnym momencie w dającej się przewidzieć przyszłości .

Zasadniczo mówienie, że wycofanie się z użycia staticnie ma sensu. Nigdy nie zostanie usunięty z C ++ i nadal jest przydatny, ponieważ nie potrzebujesz standardowego kodu, którego potrzebujesz z nienazwanymi przestrzeniami nazw, jeśli chcesz po prostu zadeklarować funkcję lub obiekt z wewnętrznym połączeniem.

Johannes Schaub - litb
źródło
2
Cóż, wygląda na to, że uznanie za przestarzałe zachęci ludzi do używania zamiast tego nienazwanych przestrzeni nazw, co byłoby dobrą rzeczą.
sbi
1
@unaperson: Jeśli nie ma innego powodu, to dlatego, że nienazwane przestrzenie nazw zapewniają ten sam mechanizm tworzenia zmiennych, stałych, funkcji i typów wewnętrznych dla ich JT. static class ... , OTOH, nie zadziała.
sbi
2
@nbt: Ponieważ nie możesz używać statycznych symboli jako argumentów szablonu i ponieważ wielu początkujących uzna statyczne za łatwiejsze w użyciu, a następnie nie próbuje wypróbować <functional> i <algorithm> et al. Tylko krótka myśl.
Sebastian Mach,
3
„ponieważ nie potrzebujesz gotowego kodu, którego potrzebujesz z nienazwanymi przestrzeniami nazw”? Jaki „standardowy kod”? Coś poza „ namespace {” i „ }”?
towi
1
@ErikAronesty Jeśli masz „klasę lokalną” w innym pliku o tej samej nazwie, popełnisz naruszenie ODR.
LF
32

Spróbuję odpowiedzieć na Twoje pytanie, chociaż jest to stare pytanie i nie wygląda na bardzo ważne (naprawdę nie jest bardzo ważne samo w sobie ), a otrzymałem już całkiem dobre odpowiedzi. Powodem, dla którego chcę na nie odpowiedzieć, jest to, że odnosi się to do fundamentalnych kwestii ewolucji standardu i projektowania języka, gdy język jest oparty na istniejącym języku: kiedy należy wycofać, usunąć lub zmienić funkcje języka w niekompatybilny sposób?

W C ++ możliwe jest użycie słowa kluczowego static w jednostce tłumaczeniowej, aby wpłynąć na widoczność symbolu (deklaracja zmiennej lub funkcji).

Właściwie to połączenie.

W n3092 to zostało wycofane:

Wycofanie oznacza:

  • Plik intencją usunąć jakąś funkcję w przyszłości; nie oznacza to, że przestarzałe funkcje zostaną usunięte w następnej wersji standardowej lub że należy je usunąć „wkrótce” lub w ogóle. Funkcje, które nie są przestarzałe, mogą zostać usunięte w następnej wersji standardu.
  • Formalna próba zniechęcenia do jego używania .

Ta ostatnia kwestia jest ważna. Chociaż nigdy nie ma formalnej obietnicy, że twój program nie zostanie złamany, czasami po cichu, zgodnie z następnymi standardami, komitet powinien starać się unikać łamania „rozsądnego” kodu. Wycofanie się powinno powiedzieć programistom, że nieuzasadnione jest poleganie na jakiejś funkcji .

Podkreśla jednak, że ze względu na zgodność z C (i możliwość kompilowania programów w C jako C ++) wycofanie się jest denerwujące. Jednak kompilowanie programu w języku C bezpośrednio jako C ++ może już być frustrujące, więc nie jestem pewien, czy wymaga to rozważenia.

Zachowanie wspólnego podzbioru C / C ++ jest bardzo ważne, szczególnie w przypadku plików nagłówkowych. Oczywiście,static deklaracje globalne są deklaracjami symboli z wewnętrznymi powiązaniami, co nie jest zbyt przydatne w pliku nagłówkowym.

Ale problem nigdy nie polega tylko na zgodności z C, jest to kompatybilność z istniejącym C ++: istnieje mnóstwo istniejących programów w C ++, które używają staticglobalnych deklaracji. Ten kod jest nie tylko formalnie legalny, ale także rozsądny, ponieważ wykorzystuje dobrze zdefiniowaną funkcję językową w sposób, w jaki jest przeznaczony .

Tylko dlatego, że istnieje obecnie „lepszy sposób” (według niektórych) na zrobienie czegoś, nie czyni programów napisanych w starym stylu „złymi” lub „nierozsądnymi”. Umiejętność używania staticsłowa kluczowego w deklaracjach obiektów i funkcji w zakresie globalnym jest dobrze rozumiana zarówno w społecznościach C, jak i C ++, i najczęściej używana poprawnie.

W podobnym duchu nie zamierzam zmieniać rzutów w stylu C doublena static_cast<double>tylko dlatego, że „rzuty w stylu C są złe”, ponieważ static_cast<double>dodaje zero informacji i zero bezpieczeństwa.

Pomysł, że za każdym razem, gdy wymyślany jest nowy sposób zrobienia czegoś, wszyscy programiści spieszyliby się, aby przepisać swój istniejący, dobrze zdefiniowany działający kod, jest po prostu szalony. Jeśli chcesz usunąć całą odziedziczoną C brzydotę i problemy, nie zmieniasz C ++, tylko wymyślasz nowy język programowania. Pół-usunięcie jednego użycia staticprawie nie czyni C ++ mniej brzydkim.

Zmiany kodu wymagają uzasadnienia, a „stare jest złe” nigdy nie jest uzasadnieniem dla zmian w kodzie.

Przełamywanie zmian językowych wymaga bardzo mocnego uzasadnienia. Trochę uproszczenie języka nigdy nie jest usprawiedliwieniem dla przełomowej zmiany.

Podane powody static jest zły, są po prostu wyjątkowo słabe i nie jest nawet jasne, dlaczego zarówno obiekty, jak i deklaracje funkcji nie są razem przestarzałe - nadanie im innego traktowania prawie nie czyni C ++ prostszym lub bardziej ortogonalnym.

Więc naprawdę jest to smutna historia. Nie z powodu praktycznych konsekwencji, jakie miał: miał dokładnie zero praktycznych konsekwencji. Ale ponieważ pokazuje wyraźny brak zdrowego rozsądku ze strony komitetu ISO.

ciekawy facet
źródło
5
Jak sam zauważyłeś, celem jego wycofania jest zniechęcenie do jego używania. Jednak nie argumentujesz, że zniechęcanie do jego używania jest złe. Mam nadzieję, że nikt nie zachęca ludzi do używania statycznych deklaracji obejmujących obszar nazw zamiast anonimowych przestrzeni nazw. Nie, chyba że specjalnie muszą skompilować krzyżowo C.
Nicol Bolas,
2
Nie obchodzą mnie ludzie używający zasięgu globalnego staticlub anonimowych przestrzeni nazw, nie zachęcam ani nie zniechęcam. Chodzi mi o to, że jeśli naprawdę chcesz zniechęcić ludzi do używania anonimowych przestrzeni nazw, musisz dać im dobry argument. W praktyce uważam, że w większości implementacji encje zadeklarowane w nienazwanej przestrzeni nazw są symbolami eksportowanymi z losową nazwą, powiększając tym samym tabelę eksportu. Podmioty zadeklarowane jako staticOTOH nie są w żaden sposób eksportowane. Tak więc wiele osób decyduje się na podstawie tej obserwacji static.
curiousguy
2
Jak sam zauważyłeś, celem jego deprecjonowania jest zniechęcenie do jego używania. ” Punktem zniechęcenia do jego używania jest to, że pewnego dnia może zniknąć. Chodzi mi o to, że zakres przestrzeni nazw staticnigdy nie zniknie, więc niewłaściwe jest jego wycofywanie. „ Jednak nie argumentujesz, że zniechęcanie do jego używania jest złe. ” Nie widziałem żadnego przekonującego argumentu, który wskazywałby, że użycie zakresu przestrzeni nazw staticjest „niewłaściwe”. Deprecjonowanie go tylko po to, aby zniechęcić do jego używania, jest złe, ponieważ nikt tak naprawdę nie wierzy, że zniknie, i ponieważ nie przekonuje ludzi, że używanie go jest „złe”.
curiousguy
5
Cały język „pewnego dnia zniknie”. Odrzućmy C ++.
Lightness Races in Orbit
2
„W podobnym duchu nie zamierzam zmieniać rzutowania w stylu C na double na static_cast <double> tylko dlatego, że„ rzutowania w stylu C są złe ”, ponieważ static_cast <double> dodaje zero informacji i zero bezpieczeństwa.” Moja odwieczna walka z wieloma inżynierami oprogramowania, którzy wciąż narzekają na moje swobodne używanie rzutów w stylu C z jednego prymitywu na drugi.
Makogan,
14

Przestarzałe lub nie, usunięcie tej funkcji języka złamałoby istniejące kody i zirytowało ludzi.

Cała statyczna dezaprobata polegała na myśleniu życzeniowym w stylu „anonimowe przestrzenie nazw są lepsze niż statyczne” i „odwołania są lepszymi wskaźnikami”. Lol.

Maxim Egorushkin
źródło
1
„Referencje są lepszymi wskazówkami”? Nie, inteligentne wskazówki to mądrzejsze wskazówki. Nie można używać odwołań do pamięci przydzielonej ze sterty, błędu, wolnego magazynu.
Dan Breslau
3
Przepraszam, zapomniałem zakończyć to ironiczną uśmiechem.
Maxim Egorushkin
2
@Dan: Dokładnie to mówi ta odpowiedź: „myślenie życzeniowe” według podobnego błędnego sposobu myślenia. Nienazwane przestrzenie nazw są ważną cechą, podobnie jak global-scope-static, chociaż z nieco innych powodów i nawet jeśli nakładają się na siebie w zastosowaniu.
Fred Nurk,
@Fred, @Maxim: Przepraszam, jeśli źle zrozumiałem lub jeśli moja pamięć jest wadliwa. Ale nie kategoryzuję „referencje są lepszymi wskaźnikami” jako równoważne z „anonimowymi przestrzeniami nazw są lepsze niż statyczne” w przypadku pobożnych życzeń. Doskonale zdaję sobie sprawę z próby zrobienia tego drugiego kija, ale nie pamiętam, żeby ktokolwiek składał poważną propozycję zastąpienia wskaźników referencjami. Ponownie, może brakuje mojej własnej świadomości.
Dan Breslau,
1
@DanBreslau: char* foo = new char; char& ref = *foo;To, że na początku otrzymałeś wskaźnik, nie mówi nic o twojej zdolności do używania referencji.
Wyścigi lekkości na orbicie