noexcept-Operator gibt Compilation Error mit GCC aber nicht mit Clang
-
Hallo
Folgender Code generiert einen Compilation Error mit GCC 7.2.0 aber nicht mit Clang 4.0.1:
struct foo { void f() noexcept { } void g() noexcept( noexcept( f() ) ) { } };
Live: GCC, Clang
Hier bin ich mir ziemlich sicher, dass Clang recht hat, denn der Operand desnoexcept
-Operators sollte nicht evaluiert werden.Ändert man nun
foo
zu einem Klassentemplate, dann kompiliert der Code lustigerweise fehlerfrei mit beiden Compilern.
Live: GCC, ClangUnd noch kurioser: Ändert man den
noexcept
-Operator zunoexcept( f )
, dann kompiliert der Code zwar mit GCC aber nicht mehr mit Clang.
Live: GCC, Clang
Hier verstehe ich nicht, wieso der Clang-Compiler einen Fehler generiert, dennf
ist doch einfach der Member-Funktionszeiger und so etwas wienoexcept( nullptr )
ist ja auch erlaubt.Hat jemand den Durchblick, was hier geschieht?
LG
-
Fytch schrieb:
Hier bin ich mir ziemlich sicher, dass Clang recht hat, denn der Operand des
noexcept
-Operators sollte nicht evaluiert werden.Das ist nicht der entscheidende Punkt, sondern dass die Transformation von Namen von Membern zu member access expressions auch auf Operanden von
noexcept
angewandt wird. Das war u.a. core issue 1207. GCC ist einfach verbuggt: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52869Fytch schrieb:
Ändert man nun
foo
zu einem Klassentemplate, dann kompiliert der Code lustigerweise fehlerfrei mit beiden Compilern.
Live: GCC, ClangDas ist ein Trugschluss. Du führst keine Instantiierung des
noexcept
-specifiers herbei, siehe [temp.inst]/2. Der GCC bug tritt weiterhin auf: http://coliru.stacked-crooked.com/a/5ffeadeeb18cfebeFytch schrieb:
Und noch kurioser: Ändert man den
noexcept
-Operator zunoexcept( f )
, dann kompiliert der Code zwar mit GCC aber nicht mehr mit Clang.
Live: GCC, Clang
Hier verstehe ich nicht, wieso der Clang-Compiler einen Fehler generiert, dennf
ist doch einfach der Member-Funktionszeiger und so etwas wienoexcept( nullptr )
ist ja auch erlaubt.[except.spec]/2 schreibt vor, dass der Ausdruck eine *contextually converted constant expression of type
bool
*ist. Die Konvertierungen sind beschränkt wie in [expr.const]/5 beschrieben. Boolean conversions, die für die Konvertierung eines Funktions-lvalues zu einembool
nötig sind, werden nicht aufgezählt; somit hat Clang Recht.noexcept(nullptr)
ist aus dem selben Grund ill-formed, obwohl alle Compiler es problemlos kompilieren.
-
Vielen Dank für die Aufklärung.
Arcoth schrieb:
[except.spec]/2 schreibt vor, dass der Ausdruck eine *contextually converted constant expression of type
bool
*ist. Die Konvertierungen sind beschränkt wie in [expr.const]/5 beschrieben. Boolean conversions, die für die Konvertierung eines Funktions-lvalues zu einembool
nötig sind, werden nicht aufgezählt; somit hat Clang Recht.noexcept(nullptr)
ist aus dem selben Grund ill-formed, obwohl alle Compiler es problemlos kompilieren.Ich glaube, hierbei handelt es sich um den
noexcept
-Operator, nicht um den von dir verlinktennoexcept
-Specifier. Folglich solltenoexcept(nullptr)
sowie auchnoexcept(f)
well-formed sein.
-
Sorry, ich war noch völlig dösig als ich das geschrieben habe. Ich dachte zuerst, du meintest
void g() noexcept(f) {}
Aber auch deine Variante ist ill-formed.
f
ist eine Memberfunktion (ich habe irgendwann einfach angenommen, sie sei es nicht...), und der Ausdruck
(*this).f
, in den dein Operand überführt wird, darf nur auf der linken Seite eines Funktionsaufrufes stehen. Dahingegen istnullptr
natürlich ein wohlgeformter Ausdruck.
-
Okay, danke dir Arcoth.
Falls jemand dasselbe Problem hat, über den Thread stolpert und nach einem Workaround sucht: Ich habe einfach einen
static constexpr bool x = ...;
innerhalb der Klasse angelegt, der dennoexcept
-Wert hält. Danach habe ichf
undg
jeweils mitnoexcept(x)
deklariert. Funktioniert, solange nicht sowohlf
ein Funktionstemplate ist und seinnoexcept
-Specifier von den Template-Argumenten abhängt.LG