2013-06-08 21 views
11

Funkcja constexpr musi składać się tylko z instrukcji return i każdy argument powinien być znany w czasie kompilacji:constexpr - dlaczego tylko zwrotne oświadczenie?

// constexpr functions use recursion rather than iteration 
constexpr int factorial(int n) 
{ 
    return n <= 1 ? 1 : (n * factorial(n-1)); 
} 

Dlaczego tylko instrukcji return? Mam na myśli, dlaczego to jest złe?

// constexpr functions use recursion rather than iteration 
constexpr int factorial(int n) 
{ 
    int a = 222; //another variable 
    return n <= 1 ? 1 : (n * factorial(n-1)); 
} 
+7

Podejrzewam, że jest to po prostu sposób na uproszczenie implementacji kompilatora. – juanchopanza

+10

Ponieważ Standard tak mówi. Zezwolenie na bardziej ogólne funkcje znacznie komplikowałoby życie pisarzy kompilatorów (zresztą C++ 14 usuwa niektóre z tych ograniczeń). –

+3

Ponieważ dopuszczanie zmiennych oznaczałoby dodanie wielu innych (bardziej skomplikowanych) ograniczeń. Utrzymywali więc prostotę ich wprowadzenia. Są na to sposoby i tak (na przykład wywołanie funkcji 'constexpr' z innej) – Dave

Odpowiedz

6

Upraszcza wdrażanie, jak mówi Andy Prowl. To prawdopodobnie odpowiada "Dlaczego", ale nie mówi, jak to robi.

Funkcja z tylko wartością zwracaną, a dokładniej bez zmiennych lokalnych, jest szczególną sytuacją dla kompilatora. Ta funkcja składa się obecnie z pojedynczego wyrażenia: funkcja AST musi mieć tylko jeden root. Ten brak zmiennych oznacza, że ​​to wyrażenie można ocenić bez pełnowymiarowej maszyny wirtualnej, aby go przetworzyć, można użyć prostego ewaluatora wyrażeń drzewa. Z różnych powodów kompilator prawdopodobnie ma już takiego ewaluatora lub może go stosunkowo łatwo utworzyć (staje się przepustką do uproszczenia drzewa).

Wiedząc, że tylko wyrażenie constexpr jest używane wewnątrz wyrażenia, zapewnia również podstawowe uproszczenie. Gwarantuje to, że każdy wierzchołek w funkcji AST ma te same właściwości, nawet jeśli jest to wywołanie funkcji. Cały mechanizm constexpr jest wówczas uogólnioną formą składania składanego. I choć nie zawsze odbywa się to na tak wysokim poziomie w kompilatorze, zapewnia to, że można go wdrożyć bez dużego wysiłku (w porównaniu do pełnej maszyny wirtualnej).

Powrót do pytania "dlaczego". Ograniczeniem są przede wszystkim ograniczenia zasobów u dostawców. Ta funkcja, jak określono, nie jest wielkim wysiłkiem, a zatem dostawcy mogą ją wdrożyć w rozsądnym czasie. Jeśli nie było takich ograniczeń, w szczególności dopuszczając zmienne lokalne, znacznie zwiększa to ilość potrzebnej pracy. Z punktu widzenia użytkownika (nas, programistów) ograniczenia są jednak całkowicie arbitralne.

+0

Dobra odpowiedź. 'constexpr' tak naprawdę prosi kompilatora, aby ** interpretował ** (zamiast kompilować), więc dążenie do prostoty jest zrozumiałe. Dobrym dodatkiem byłoby jednak "static if" (przydatne dla 'constexpr', nie tylko dla szablonów), o którym statusie nie jestem teraz pewien. – eudoxos

+0

Myślę, że to także z innego powodu. Nie można mieć nieskończonych pętli, a nieodwołalne wywołania rekursywne mogą być wykrywane po prostu przez forcin limit rekursji. Również każda zmiana na constexpr pozwalająca na więcej rzeczy implikuje również bardziej złożone niezmienniki, których użytkownicy muszą przestrzegać, aby skompilować kod bez błądzenia, dlaczego nie jest on kompilowany. Mam również wątpliwości, że tak naprawdę musisz "udowodnić", że constexpr działa, a stworzenie go dla dowolnego kodu byłoby trudne lub niemożliwe również z teoretycznego punktu widzenia. – GameDeveloper

13

Dlaczego:

Ponieważ constexpr jest dość nowy i radykalna koncepcja w C++ 11 i trudno jest przejść główną normę językową na coś zupełnie nowego. Zasady konserwatyzmu.

Dla C++ 1y (obecnie ukierunkowane na C++ 14), twój przykład jest legalny. Porada klangu bagażnika już implementuje go pod flagą -std=c++1y.

Powiązane problemy