C ++ Lambda Standardargumente Compiler Fehlverhalten?
Welche der folgenden C ++ - Lambdas / -Anweisungen sollen gemäß der neuesten C ++ - Spezifikation funktionieren?
Kontext für den Fall, dass dies relevant ist: siehe hier .
Ich habe die folgenden Codefragmente mit -std=c++17Fedora 33 mit clang 11.0.0 und gcc 10.2.1 getestet.
Update: Ersetzen __PRETTY_FUNCTION__durch __func__für Standardkonformität. Das gleiche Verhalten kann beobachtet werden.
Update2: Beispiel für die Verwendung const char * s = __func__als Standardargument, um zu überprüfen, ob es innerhalb eines Funktionsbereichs gültig sein soll (dank @BenVoigt).
1. LLVM __func__innerhalb des Lambda-Standardarguments
void clang() {
[](const char* c = __func__) {std::cout << c << std::endl;}();
}
Erwartetes Verhalten (CLANG):
- Ausdrucken
clang\n(void clang()für__PRETTY_FUNCTION__)
Beobachtetes Verhalten (CLANG):
- Compiler-Warnung:
warning: predefined identifier is only valid inside function [-Wpredefined-identifier-outside-function] - Ausdrucken
\n(top level()für__PRETTY_FUNCTION__)
2. GCC ignoriert Aussagen
template <typename L>
constexpr std::string_view methodName(L l) { return l(); }
#define __METHOD_NAME__ (\
__func__, /* needed for pointer to work */ \
methodName([](const char* c = __func__) {return std::string_view(c);}) \
)
void gcc1() {
std::cout << [](const char* c = __func__) { return c; }() << std::endl; // GCC: This statement doesn't do anything
std::cout << [](const char* c = __func__) { return c; }("gcc") << std::endl;
std::cout << __METHOD_NAME__ << std::endl; // GCC: This statement somehow conflicts with the statements above
}
void gcc2() {
std::cout << __METHOD_NAME__ << std::endl; // GCC: This statement itself works
}
Erwartete Leistung (GCC):
gcc1
gcc
gcc1
gcc2
Beobachtete Ausgabe (GCC):
gcc
gcc2
3. GCC-Kompilierungsfehler
void gcc3() {
std::string_view s = [](const char* c = __func__) { return std::string_view(c); }();
std::cout << s << std::endl;
}
Erwartetes Verhalten (GCC): Kompiliert ohne Probleme.
Beobachtetes Verhalten (GCC): error: internal compiler error: in finish_expr_stmt
Antworten
[class.local] Die lokale Klasse befindet sich im Bereich des umschließenden Bereichs und hat denselben Zugriff auf Namen außerhalb der Funktion wie die umschließende Funktion. [Hinweis: Eine Deklaration in einer lokalen Klasse kann eine lokale Entität aus einem umschließenden Bereich nicht odr-verwenden (6.2). - Endnote]
Ein Lambda ist eine lokale Klasse und kann daher keine anderen Variablen aus dem umschließenden Bereich (z. B. __func__) als in seiner Erfassungsklausel verwenden.