2015-07-14 13 views
5

ja natknąłem nowej C++ 14 podpisu dla std::max funkcję:kłopoty ze zrozumieniem C++ 14 Relaxed ograniczenia constexpr

template< class T > 
const T& max(const T& a, const T& b); // (C++11) 

template< class T > 
constexpr const T& max(const T& a, const T& b);// (C++14) 

Czytałem o zrelaksowany ograniczeń constexpr propozycję dla C++ 14 ale ja nadal nie rozumiem dlaczego funkcja ta zwracana wartość może być constexpr

Przykład:

std::vector<int> a, b; 
//This does not compile but as my understadnding of `constexpr` this should 
int array[std::max(a.size(), b.size()]; (1) 
//This is trivial use that does compile 
int array[std::max(1,2)]; (2) 

Podczas wywoływania std::max w (1) constexpr jest ignorowane?

+0

'constexpr' tutaj nie oznacza, że ​​funkcja zwraca wartość' constexpr'. Oznacza to, że funkcją jest 'constexpr'. (Podobnie jak "static int x();" nie oznacza, że ​​'x' zwraca statyczną int). –

Odpowiedz

10

Podstawowy problem nie jest bezpośrednio związany z rozluźnionymi regułami constexpr, funkcja constexpr jest tylko stałym wyrażeniem, jeśli argumenty są wyrażeniami stałymi. W twoim drugim przypadku:

int array[std::max(1,2)]; 

to działa, ponieważ liczby całkowite są rzeczywiście stałymi wyrażeniami.

C++ 11 była bardziej specyficzna w tym przypadku standardowe dla Projekt C++ 11 w sekcji 5.19[expr.const] określa się przypadki, w których sub ekspresja nie jest uważany za stały ekspresji i zawiera następujący:

prosząc o funkcji constexpr argumentów, że gdy podstawiony przez podstawienie funkcji wywołania (7.1.5) nie uzyskanie stałej ekspresji;

C++ 14 ustęp ten usunięto i mają następujące wyjątki:

jest wywołanie funkcji innej od konstruktora constexpr dla dosłownym klasy, w zależności constexpr, lub niejawne wywołanie trywialnego destruktora (12.4) [Uwaga: Rozdzielczość przeciążenia (13.3) to zastosowana w zwykły sposób -end note];

i musimy wykorzystać resztę zasad w odniesieniu do argumentów (sub-wyrażeń).

W pierwszym przypadku:

int array[std::max(a.size(), b.size()]; 

std::vector::size nie zaznaczono constexpr a więc podlega wyżej cytowanej wyjątku.

Należy również zauważyć, że w części 7.1.5[dcl.constexpr] mamy następujące:

Wywołanie funkcji constexpr daje taki sam wynik jak wywołanie o podobnej funkcji w innych niż constexpr wszystkie aspekty z wyjątkiem tego, że wywołanie do funkcji constexpr może pojawić się w wyrażeniu stałym.

Przekazywanie argumentów do funkcji constexpr, które nie są wyrażeniami stałymi, oznacza po prostu, że wyrażenie nie jest dostępne dla zastosowań w kontekstach wymagających stałego wyrażenia.

Jak DYP wskazuje, że std::max nie powstał constexpr w 11 ze względu do różnych kwestii C++ prawdopodobnie tym komisja jest konserwatywne i ograniczony czas, możemy zobaczyć niektóre z zagadnień w N3039. to zapomnienia zobaczyć N3856 który mówi:

Ten krótki dokument proponuje, aby standardowych funkcji MIN i MAX constexpr. Byli na szczycie listy motywujących przypadków dla obniżania parametrów referencyjnych dla funkcji constexpr w C++ 11. Zostali zapomniane po zmianie języka rdzeń został przyjęty

Dla odniesienia wiemy, że 1 i 2 są stałe wyrażenie z sekcji 5.19 który mówi:

Dosłowne stała wyrażenie jest prvalue rdzeń stałym wyrażeniem typu literowego, ale nie typu wskaźnika. Stałe wyrażenie całkowe jest dosłownym ciągłym wyrażeniem typu wyliczeniowego całkowego lub nieskrępowanego. [...]

+0

Pomyślałem, że jeśli funkcja zostanie zadeklarowana jako 'constexpr', to można ją wywołać tylko z wartościami, które można obliczyć podczas kompilacji, inaczej będzie to błąd czasu kompilacji ... –

+0

@AlejandroFreeman zaktualizowana odpowiedź –

+0

@dyp wiesz, że znalazłem [ lwg 2350] (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3893.html#2350), ale byłem zdezorientowany, ponieważ wyszedł z wp -> open i nie mogłem dowiedzieć się, dlaczego –

Powiązane problemy