2012-12-19 8 views
10

Deklaratory. Tak, deklaratorzy. Są źródłem wielu debat poświęconych konwencjom kodowania. To naprawdę dobry temat na argumenty - C++ nie rządzi tym, który jest lepszy od drugiego (to nie obchodzi!). A więc możemy napisać to bez obaw może wyśmiać kogoś z was:Declarator pozycja modyfikatora w szablonach variadic

int x; 

int& a = x; 
int &b = x; 

int* c = &x; 
int *d = &x; 

Pod względem składniowym, b i d są „bardziej poprawny” niż inni. Wymagane jest umieszczenie modyfikatorów deklaratora przed nazwami:

int m, *n; // m is an int; n is a pointer to int 

Ale wydaje się, że fala przemawia na korzyść jednego. Z C++ 11 w zmiennej liczbie argumentów szablonów, pozycja declarators wydaje się być ograniczone do formularza gdzie modyfikatory są bliżej Typ podstawy:

template<typename... Ts> 
void VariadicFuncRef(const Ts&... args) { } 
          ^
template<typename... Ts> 
void VariadicFuncPtr(Ts*... args) { } 
        ^

Jest błędem napisać te formy:

template<typename... Ts> 
void VariadicFuncRef(const Ts... &args) { } 

template<typename... Ts> 
void VariadicFuncPtr(Ts... *args) { } 

Dla konkretnego przykładu kliknij here.

Moje pytanie brzmi: Dlaczego ograniczamy się do tej (prawnej) formy i nie możemy używać drugiej?

Jakieś myśli?

ADDITIONAL 1: Jestem również zainteresowany decyzją projektową o tym, dlaczego ta "reguła" jest "egzekwowana".

+0

+1. Przy okazji, dobre pytanie. – Nawaz

+0

@Nawaz Przyszło mi do głowy, kiedy spędziłem kilka minut próbując skompilować kod z niewłaściwą składnią. Lekcja: nigdy nie korzystaj z funkcji, z którymi nie jesteś dobrze przyzwyczajony. –

+0

To przywróci twój świat: trzy ... są również częścią deklaratora! –

Odpowiedz

3

Po pierwsze, nie powiedziałbym, że int &a jest bardziej aktualny niż int& a. Możesz powiedzieć, że jest to bardziej czytelne lub dobra praktyka, ale to zupełnie inna sprawa.

Drugi parametr rozpakować składnia T... można odczytać jako „typ-wzór na lewej stronie ... rozpręża się, tworząc takie same lub różne typy parametrów rzeczywista funkcja dopasowania formę wzór typu”. Więc kiedy napiszesz f(T&...), możesz go rozszerzyć do f(int&, float&, double&, Xyz&, Abc&). Ale to nie wydaje się być tak oczywiste (przynajmniej dla mnie), gdy składnia jest T...&. Być może jest to jeden z wielu możliwych powodów, dla których Standard tak to zrobił.

Należy również pamiętać, że args w T&...args jest opcjonalnie. Więc jeśli go nie napiszesz, to void f(T...&) wygląda dziwnie (przynajmniej dla mnie) i void f(T&...) wygląda co najmniej estetycznie.

Można również porównać składnie takie jak: T * const & ... z T... * const &. Wzór typu jest bardziej oczywisty w poprzedniej składni niż w drugim.

+0

Dobra rada. Niestety moglibyśmy również powiedzieć, że '& args' w' T ... & arg' (jeśli to jest poprawne) rozwija się w, na przykład 'int &, float & ...'. –

+0

Hahaha! Estetyka kodu! –

+1

Jestem nieco przekonany twoją odpowiedzią. Wielkie dzięki. Ale mogę też korzystać z opinii osób trzecich. Mam nadzieję, że możesz pozwolić sobie na czekanie. –

4

Stara składnia deklaratora była po prostu jedną regułą z niewielką białą spacją, ale twój pomysł jest dwa. Wątpię, czy komisja opowiadałaby się za wprowadzeniem dwóch zasad, gdy jeden byłby wystarczający.

Wybór stawianie declarator po lewej zostało wykonane najprawdopodobniej z dwóch powodów:

  • idiomatycznym C++ obecnie preferuje int* x zamiast int *x (Bjarne wykorzystuje były na przykład). Większość uważa składnię deklaratora za błąd.
  • Rozszerzenie pakietu parametrów rozszerza elementy na lewo od ..., a nie na prawo.
+0

Czy mógłbyś rozwinąć swój drugi punkt? –

+0

@MarkGarcia 'std :: forward (args) ..., args' rozwija paczki po lewej stronie' ... ', nie jest prawe. – Pubby

+0

W porządku. To jest całkowicie poza moją ligą ('std :: forward'). Ale się uczę! (Nie ma potrzeby opracowywania 'std :: forward') –

2

Doskonałość osiąga się nie wtedy, gdy nie ma nic więcej do dodania, ale kiedy nie pozostaje nic do zabrania.

- Antoine de Saint-Exupéry

Trudność w konstrukcji języka programowania nie jest dodanie możliwości, jest powstrzymanie się od dodawania ich. Każdy element, każdy wariant składni, ma swoją cenę:

  • muszą być specjalnie kodowane w kompilator
  • one stwarzają ryzyko wprowadzenia błędów
  • one stwarzać ryzyko interakcji źle z inną cechą/Odmiana
  • ...

The składni w C i C++ jest (w większości) spacje nieczuły, więc to nie ma znaczenia, gdzie umieścisz & lub * a obie preferencje mogą współistnieć bez dodatkowego obciążenia; jednak w przypadku szablonów variadycznych ma to znaczenie z powodu tokena .... W związku z tym komisja zdecydowała się wybrać jedną i wybrała najbardziej idiomatyczne w C++ (które kładą nacisk na pełny typ, a nie na typ podstawowy).