9

Podczas wytwarzania MCVE dla this problemu natknąłem, Znalazłem następujące rozbieżność między kompilatory:Deklaracja przekazania funkcji `constexpr` wewnątrz innej funkcji - Błąd kompilatora?

Rozważmy następujący kod:

// constexpr int f(); // 1 

constexpr int g() { 
    constexpr int f(); // 2 
    return f(); 
} 

constexpr int f() { 
    return 42; 
} 

int main() { 
    constexpr int i = g(); 
    return i; 
} 

Ten kod kompiluje się na Clang 3.8.0, ale nie na GCC 6.1.0 z:

error: 'constexpr int f()' used before its definition 

zakomentowanie // 2 i odkomentowanie // 1 prace na obu kompilatorów.

ciekawe, przesuwając f „s definicji zamiast // 1 kompilacji, ale wyzwala ostrzeżenie przy // 2:

warning: inline function 'constexpr int f()' used but never defined 

Który kompilator ma rację?

+1

Standard nie wydaje się całkiem jasny. Potrzebujemy silnego prawnika tutaj :) – Arunmu

Odpowiedz

2

Wymiana funkcje constexpr z inline funkcji zachowuje dokładnie ten sam problem (to jest w porządku z globalnym deklaracji 1, ale nie z deklaracją funkcja-ZAKRES 2.) Ponieważ constexpr implikuje inline to wydaje się, że przyczyny.

W tym przypadku, z deklaracją 2, GCC narzeka: warning: 'inline' specifier invalid for function 'f' declared out of global scope i warning: inline function 'int f()' used but never defined. Nie można połączyć ("undefined reference to 'f()'").

Wygląda więc na to, że rezygnuje z wpisywania, wywołuje wywołanie, ale nie ma problemu z emitowaniem kodu dla f(), ponieważ wszystkie zastosowania są wstawiane (?), Więc połączenie nie działa.

i Clang narzeka: error: inline declaration of 'f' not allowed in block scope

Od constexpr implikuje inline wydaje się, że ta zasada, że ​​deklaracje inline nie są dozwolone w ramach grupowego powinien również mieć zastosowanie do constexpr, a więc GCC jest poprawny. Ale standard nie wydaje się wyjść i powiedzieć to. W projekcie, którego dotyczyłem, zasada dotycząca inline znajduje się w §7.1.2 [dcl.fct.spec], część 3: "Wewnętrzny specyfikator nie pojawia się w deklaracji funkcji zakresu bloków", ale nic podobnego nie pojawia się o constexpr.