Dlaczego ten kod zajmuje tyle czasu, aby skompilować się z g ++?

12

Rozważ następujący kod:

template<int i> class A
{
    typedef A<i-1> B;
    B x, y;
};
template<> class A<0> { char m; };
int main()
{
    A<LEVEL> a;
}

Podczas testowania jego kompilacji przez g ++ za pomocą następującego polecenia Bash (z g ++ 8.3.0)

for ((level=1; level<30; ++level)); do
    echo -n ${level},
    /usr/bin/time -f %U g++ -DLEVEL=$level test.cpp -o /dev/null
done

Otrzymuję następujące dane wyjściowe:

1,0.03
2,0.03
3,0.04
4,0.04
5,0.04
6,0.04
7,0.04
8,0.04
9,0.03
10,0.04
11,0.02
12,0.04
13,0.02
14,0.03
15,0.04
16,0.05
17,0.05
18,0.08
19,0.11
20,0.20
21,0.35
22,0.67
23,1.30
24,2.52
25,5.02
26,10.23
27,19.96
28,40.30
29,80.99

Czas kompilacji jest wykładniczy LEVEL. Ale jeśli zmienię B x, y;na B x[2];, kompilacja odbywa się w stałym czasie (~ 30 ms).

Dlaczego tak się dzieje? Pomyślałem, że skoro kompilator wie, że Bjest jeden i ten sam typ dla obu xi yzajęłoby tyle samo czasu jak kompilacji x[2]. Ale z jakiegoś powodu wygląda inaczej. Czy mogę w jakiś sposób wymusić Brealizację (w przeciwieństwie do zwykłego aliasu), aby g ++ mógł utworzyć obie zmienne tak łatwo, jak stworzył tablicę?

Ruslan
źródło
1
Technicznie poprawna, ale bezużyteczna (dla ciebie) odpowiedź: załataj kompilator.
Botje,
5
Dlaczego miałbyś to tutaj opublikować? Gcc ma bugzillę do zgłaszania problemów ... Najpierw jednak sprawdź najnowszą wersję.
Marc Glisse,
@MarcGlisse Miałem nadzieję, że może istnieć dobre wytłumaczenie lub obejście. Nie jestem pewien, czy uznam to za błąd, który warto naprawić, jeśli zgłosię go jako taki.
Ruslan
3
Mają nawet słowo kluczowe „czas kompilacji” dla przypadków, w których kompilacja trwa zbyt długo, więc tak uważają, że warto to naprawić (co nie znaczy, że zrobią to natychmiast). Dlatego szczególnie, jeśli widzisz inny kompilator, który nie ma zachowania wykładniczego (więc wiesz, że można tego uniknąć), zgłoś to. Cóż, może sprawdź, czy widzisz coś bardzo podobnego w bazie danych, ale jest ok, jeśli przegapisz nieoczywisty duplikat.
Marc Glisse,
5
@MarcGlisse zgłosił: gcc.gnu.org/bugzilla/show_bug.cgi?id=91990
Ruslan

Odpowiedzi:

1

Ponieważ w twoim wystąpieniu g ++ występuje błąd. Nie powinno, a jak skomentował @Marc Glisse, powinieneś to zgłosić (co zrobiłeś w momencie pisania)

Możesz wtedy usunąć swoje pytanie (mądrzejszy wybór). Lub zaakceptuj tę odpowiedź.

Hejji
źródło