C ++ Lambda Standardargumente Compiler Fehlverhalten?

Oct 16 2020

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

n.'pronouns'm. Oct 16 2020 at 17:01

[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.