2017-03-27 1 views
4

sein, was ich bin versuchen, Ausnahmen zu tun ist, essen, wenn ein Objekt konstruieren, dass ungültig sein kann. Es wäre perfekt für die Verwendung von std::optional, aber ich glaube nicht, die Auslassung von std::optional ändert den Fehler, den ich sehe: das Objekt wird erfasst und verwendet, bevor es initialisiert wurde. Ich glaube nicht, dass es in erster Linie eingefangen werden sollte, weil wir nach meinem besten Wissen keinen Sequenzpunkt erreicht haben (zählt eine Lambda-Initialisierung als Sequenzpunkt?). Darüber hinaus ist der Bug IMO leicht abfangbaren menschlichen Fehler (und sogar gefangen werden ... abhängig von den Umständen).Lambda-Erfassung bei der Initialisierung soll ein Fehler

Wie (wichtiger, warum) ist das Lambda in der Lage, die noch nicht initialisierten foo zu erfassen und zu verwenden?

https://godbolt.org/g/IwcHrV

#include <string> 
using namespace std; 

void foo() { 
    string foo = [&]()->string{ 
    // using foo before it's been initialized == undefined behavior 
    auto guessed_foo = to_string(1234); 
    if (begin(foo) == end(foo)) { 
     return guessed_foo; 
    } 
    return {}; 
    }(); 
} 

Compiler exited with result code 0

Aber ... die Deklaration von string foo mit auto fooersetzt hat erscheint eine Fehlermeldung ähnlich zu verursachen, was Ich mag, Sie zu sehen.

https://godbolt.org/g/GfE4WH

#include <string> 
using namespace std; 

void foo() { 
    auto foo = [&]()->string{ 
    auto guessed_foo = to_string(1234); 
    if (begin(foo) == end(foo)) { 
     return guessed_foo; 
    } 
    return {}; 
    }(); 
} 

error: variable 'foo' declared with 'auto' type cannot appear in its own initializer

Bitte beachte, dass ich dies mit GCC 6.2 auf Ubuntu 16.04 LTS gefunden. Die Konfiguration in Godbolt benutzt clang 3.9.1. Beide sind für C++ 14 konfiguriert.

Also meine Fragen sind:

  • Warum ist die Lambda-Erfassung für eine Initialisierung eines Nicht-Auto-deklarierte Variable der Lage, die (noch nicht initialisiert) Variable zu erfassen und zu nutzen?
  • Warum wird auto (meiner Meinung nach richtig) gefangen und fehlerhaft?
  • Darüber hinaus, warum der Unterschied zwischen den beiden oben? Es klingt wie Compilerfehler, aber ... gibt es etwas Spezifisches im Standard, das dies als korrektes Verhalten deklariert?
  • Dies könnte als ein Argument fürauto Schlüsselwort genommen werden?
+4

stark verwandt: http: // stackoverflow.com/questions/11186261/why-ist-int-i-i-legal – NathanOliver

Antwort

2

Der zweite Schnipsel läuft in [dcl.spec.auto]/10:

If the type of an entity with an undeduced placeholder type is needed to determine the type of an expression, the program is ill-formed.

Die Art der foo benötigt, um den Typ des Ausdrucks foo innerhalb der Lambda-Körper zu bestimmen, aber an diesem Punkt haben Sie nicht foo abgeleitet ' s Typ noch, so ist das Programm schlecht gebildet.


Wie, warum Sie berechtigt sind, etwas vor der Initialisierung zu erfassen, sehen im Allgemeinen Why is 'int i = i;' legal?. Wir haben viele Beispiele für rekursive Lambda mit std::function:

std::function<void(int)> foo = [&foo](int i){ return foo(i - 1); }; 
+0

Okay, also warum gibt '-Winit-self -Wuninitialized' eine Diagnose für' int i = i; 'aus, aber nicht _ aus dem Lambda-Ausdruck? https://godbolt.org/g/qC2iao – inetknght

+2

@inetknght Dies sind Best-Effort-Warnungen, nicht garantiert. –

Verwandte Themen