2015-11-01 15 views
18

Na przykład:Czy możemy pominąć const dla zmiennych lokalnych w funkcjach constexpr?

constexpr int g() { return 30; }  

constexpr int f() 
{ 
    // Can we omit const? 
    const int x = g(); 
    const int y = 10; 

    return x + y; 
} 

Czy istnieje dowolny punkt, aby kiedykolwiek zadeklarować zmienne lokalne w constexpr funkcji z const?

nie są constexpr funkcje z const zmiennych lokalnych równoważne do tych bez const?

Innymi słowy, czy constexpr na funkcji nakłada (imply) const na swoje zmienne lokalne?

+9

Nie zgadzam się z twoim założeniem, że pomijanie 'const' sprawia, że ​​funkcja wygląda" czystsza ". Poza tym, nie sądzę. Ale nie jestem "constexpr". –

+3

Możesz nawet [zmienić je] (http://ideone.com/L4Oa68)! (I to logiczne, nie tworzy funkcji _nie czystej_) – Lol4t0

+2

@LeoHeinsaar Myślę, że masz na myśli mniej nie-białych znaków, ponieważ w przeciwnym razie można to uczynić banalnie czystszym dzięki tej definicji w sposób, który będzie prawie powszechnie interpretowany jako nieczytelny. . – hvd

Odpowiedz

23

Te same argumenty do deklarowania zmiennych jak const w nie- constexpr funkcji również zastosowanie do constexpr funkcji:

  • Deklarowanie zmiennej const dokumentuje fakt, że nigdy nie będzie można zmienić. Może to w niektórych przypadkach sprawić, że funkcja będzie bardziej czytelna.
  • Deklarowanie zmiennej wpływa na rozdzielczość przeciążania i może spowodować, że h(x) zmieni się w inny sposób w zależności od tego, czy x jest const.

Oczywiście, w przeciwnym kierunku, jak wspomniano w komentarzach już:

nawet w constexpr funkcje, zmienne lokalne mogą być zmieniane. Jeśli zmienne zostaną zmienione, tak aby były const, próby ich zmiany nie będą już akceptowane.

+0

Myślę, że to jest dobra odpowiedź. Bez większego zastanowienia może sprawiać wrażenie, że 'constexpr' na jakiejś funkcji w jakiś sposób narzuca (implikuje) constness na wszystko w nim zawarte, w tym na zmienne lokalne (ponieważ, na przykład, nie można z niego wywoływać funkcji innych niż constexpr). Dzięki. –

+4

Oczywiście zmiennych lokalnych nie można przenieść z powrotem. Z tego powodu jestem bardzo ostrożny wobec stałych mieszkańców. –

1

Zasadniczo funkcja nie może być obliczona podczas kompilacji i dlatego nie można jej wywołać w wyrażeniu stałym. Określenie funkcji jako constexpr wskazuje, że można jej użyć w wyrażeniach stałych, jeśli jej argumenty wejściowe są stałe. Na przykład to ...

constexpr int n = func(7); 

... musi być oceniony podczas kompilacji.

To jest znaczenie constexpr przed funkcjami. W tym przypadku nie wynika z tego, że zmienne lokalne w funkcji nie muszą być określone jako const.

16

W ten konkretnym przykładzie zmienne lokalne byłby najlepszy oświadczył constexpr nie const, ponieważ może być obliczane w czasie kompilacji:

constexpr int g() { return 30; }  

constexpr int f() 
{ 
    constexpr int x = g(); 
    constexpr int y = 10; 

    return x + y; 
} 

Kiedy f() nazywa się w czasie pracy, bez constexpr na x i y, (z lub bez const na x i y) dajesz kompilatorowi opcję inicjowania x i y w czasie wykonywania zamiast czasu kompilacji.W przypadku constexpr na x i y kompilator jest kompilowany w czasie kompilacji, nawet gdy f() jest wykonywany w czasie wykonywania.

W innej funkcji jednak nie zawsze można użyć constexpr. Na przykład jeśli f() i g() wziął parametr:

constexpr int g(int z) { return z+30; }  

constexpr int f(int z) 
{ 
    const int x = g(z); 
    constexpr int y = 10; 

    return x + y; 
} 

Teraz x nie można oznaczyć constexpr ponieważ z nie może być stałą czasu kompilacji, a obecnie nie ma sposobu, aby oznaczyć go jako taki. Tak więc w tym przypadku oznaczenie xconst jest najlepsze, co możesz zrobić.

+1

Czy uzasadnione byłoby wymaganie implikowania 'constexpr' dla zmiennych lokalnych, które nie zostały zmienione? –

+0

@LeoHeinsaar: Obawiam się, że nie. W tym przykładzie, co jeśli 'g()' nie jest oznaczone 'constexpr'? W takim przypadku wynik 'x' nie może być oznaczony' constexpr', a kompilator ma prawa do obliczania 'g()' w czasie wykonywania. Być może 'g()' musi wykonać połączenie telefoniczne, aby uzyskać jego wynik ... –

+1

Jeśli g() nie jest oznaczone "constexpr", czy ma się nawet skompilować? Rozumiem, że możemy tylko wywoływać funkcje "constexpr" z funkcji 'constexpr' ... –

3

Nie tylko może, ale czasami koniecznością (tj Jeśli zmienna zmianami), np:

constexpr size_t f(size_t n) { 
    size_t val = 1; 
    if (n == 0) val++; 
    return val; 
} 
char arr0[f(0)] = {'a', 'x'}; 
char arr1[f(1)] = {'y'}; 

jest w porządku w C++ 14.