2015-04-03 12 views
25

Mam problem z constexpr. Książka C++ Primer przedstawia linię kodu:Użycie funkcji constexpr przed zakończeniem definicji

constexpr int sz = size(); // only size() is a constexpr function 
          // this code is right 

Jednak książka nie dać konkretny przykład. Więc staram następujący kod sam:

#include <iostream> 
constexpr int fun(); 
int main() 
{ 
    constexpr int f = fun(); 
    std::cout << f << std::endl; 
} 
constexpr int fun() 
{ 
    return 3; 
} 

Ale mój kompilator powiedział fun() jest niezdefiniowany.

Jeśli zmienię constexpr do const, to działa dobrze, a jeśli mogę zmienić kod w celu określenia funkcji constexpr przed użyciem:

#include <iostream> 
constexpr int fun() 
{ 
    return 3; 
} 
int main() 
{ 
    constexpr int f = fun(); 
    std::cout << f << std::endl; 
} 

Działa również dobrze. Czy ktoś może mi powiedzieć, dlaczego?

+1

Jakiego używanego kompilatora? – kvorobiev

+0

@kvorobiev clang, linux – icecity96

+0

Która wersja clang? – kvorobiev

Odpowiedz

15

Funkcja NIE musi być zdefiniowana przed pierwszym użyciem, jednak wynik jakiegokolwiek wywołania wykonanego przed definicją nie jest wyrażeniem stałym.

Źródło: C++ standardowe projekty n4296, rozdział 5.20:

warunkowe wyrażeniee jest rdzeń stałym wyrażeniem chyba oceny e, następujące zasady abstrakcyjnej maszyny, by oceniać jedno z następujących wyrażeń:

  • this, z wyjątkiem funkcji w constexpr lub constexpr CO nstructor, który jest oceniany jako część e;
  • wywołanie funkcji innej niż konstruktor constexpr dla klasy literalnej, funkcji constexpr lub niejawnego wywołania trywialnego destruktora [Uwaga: Rozdzielczość przeciążania jest stosowana jako zwykle - nota końcowa];
  • wywołanie niezdefiniowanej funkcji constexpr lub niezdefiniowanego konstruktora constexpr;
  • ...

wersja projektu z 3485 (sekcja 5.19):

warunkowe wyrażenie jest rdzeń stałym wyrażeniem chyba że wiąże się jeden z poniższych jako potencjalnie ocenione podwyrażenie, ale podwyrażenia logicznych AND, logiczne OR i operacje warunkowe, które nie są oceniane, nie są brane pod uwagę [Uwaga: Przeciążony operator wywołuje funkcję.- koniec uwaga]

  • this [Uwaga: przy ocenie stałej ekspresji, podstawienie funkcji wywołania zastępuje każde wystąpienie this w funkcji constexpr członu ze wskaźnika do obiektu klasy. - nota końcowa];
  • wywołanie funkcji innej niż konstruktor constexpr dla klasy literalnej lub funkcji constexpr [Uwaga: Rozdzielczość jest stosowana jak zwykle - nota końcowa];
  • inwokacja nieokreślonej constexpr funkcji lub niezdefiniowany constexpr konstruktor
  • ...

Przykład int x2 = s. t(); w n2235 rzeczywiście stał się ważny z powodu zmian dokonanych przed Normalizacyjny. Jednak constexpr int x2 = s. t(); pozostaje błędem.

+0

n4296 to szkic standardu C++. Czy kompilatory już to wspierają? – kvorobiev

+1

@kvorobiev: Cytuję z wersji roboczej, ponieważ jest publiczna. Reguła została wprowadzona wcześniej kilka szkiców i jest częścią oficjalnego standardu. –

+0

@kvorobiev możesz zobaczyć N3337 5.19/2, który jest w zasadzie ostateczną wersją standardu C++ 11. g ++/clang ++ są zgodne z C++ 11 (z niewielkimi wyjątkami) – vsoftco

3

Funkcja stałego wyrażenia musi zostać zdefiniowana przed pierwszym użyciem. Zobacz ten paper, koniec sekcji 4.1.

+0

Więc książka jest w błędzie? Być może niektóre kompilatory akceptują tę składnię, mimo że nie jest dozwolona przez standard? –

+0

Zgodnie z tym [tabela] (http://wiki.apache.org/stdcxx/C++0xCompilerSupport) kilka kompilatorów obsługuje teraz constexpr i wątpię, aby jeden z nich obsługiwał tę składnię. – kvorobiev

+0

@kvorobiev, ale najważniejsze kompilatory są w pełni przygotowane do C++ 11, w szczególności g ++/clang ++. MSVC jeszcze nie, ale się tam dostać. – vsoftco

Powiązane problemy