2016-12-22 2 views
9

Betrachten Sie den folgenden Code ein:Gelöschte Konstruktor - MSVC meldet einen Fehler, Clang nicht

class SILPassPipelinePlan final { 
public: 
    SILPassPipelinePlan() = default; 
    ~SILPassPipelinePlan() = default; 
    SILPassPipelinePlan(const SILPassPipelinePlan &) = default; 
    SILPassPipelinePlan(SILPassPipelinePlan &&) = delete; 

    SILPassPipelinePlan x() { 
    SILPassPipelinePlan P; 

    return P; 
    } 
}; 

int main() { 
    return 0; 
} 

MSVC meldet den folgenden Fehler:

1>consoleapplication2.cpp(13): error C2280: 'SILPassPipelinePlan::SILPassPipelinePlan(SILPassPipelinePlan &&)': attempting to reference a deleted function

1>consoleapplication2.cpp(8): note: see declaration of 'SILPassPipelinePlan::SILPassPipelinePlan'

Clang und GCC nicht.

Aus Sicht der Spezifikation, welcher Compiler ist korrekt? Ist das ein MSVC-Bug oder ein Clang-Bug?

MSVC stammt aus dem neuesten Visual Studio 2015 Update 3, Clang ist Version 3.9.0.

+0

Welche '-std'-Flagge übergeben Sie an Clang und GCC? Die Löschung von Move-Konstruktoren hat wichtige Änderungen zwischen C++ 11 und C++ 14 erfahren. – Angew

+0

@Angew. Keine spezifischen Flags. Probieren Sie es hier aus: http://rexttester.com/WJMW74714 –

+1

Basierend auf diesem Rextester-Link verwenden Sie '-std = C++ 14'. Sie sollten diese Informationen zu der Frage hinzufügen. – Angew

Antwort

7

C++ 11 impliziter bewegt sich in bestimmten Szenarien — yours included eingeführt:

In the following copy-initialization contexts, a move operation might be used instead of a copy operation:

  • If the expression in a return statement ([stmt.return]) is a (possibly parenthesized) id-expression that names an object with automatic storage duration declared in the body or parameter-declaration-clause of the innermost enclosing function or lambda-expression, or

  • […]

overload resolution to select the constructor for the copy is first performed as if the object were designated by an rvalue. If the first overload resolution fails, […]

Clang (. Die einzige Implementierung anzunehmen, btw) entweder falsch interpretiert "versagt", um die Auswahl der gelöschten Funktionen beinhalten oder gilt [over.match.funcs]/8 zu locker. Siehe Fehler 31025.

+0

Danke. Etwas wie 'return const_cast (P);' behebt den Fehler - aber hat das Nebenwirkungen? –

+1

@HBellamy Zum einen verhindert es, dass Kopierschutz angewendet wird. Gibt es einen bestimmten Grund, dass Sie * den Umzug ctor * löschen anstatt ihn einfach nicht zu liefern? Sie erkennen, dass die Bereitstellung eines selbst bedeutet, dass in Ihrem Fall keine implizit erklärt wird? Siehe [\ [class.copy.ctor \]/(8.1)] (http://eel.is/c++draft/class.copy.ctor#8.1). – Columbo

4

Alle Versionen von GCC auf Wandbox lehnen diesen Code ab. Testen Sie das zufällig auf einem Mac und verwenden Sie dessen Clang-Masquerading-as-GCC?

Das hat nichts mit P0135 zu tun. Clang ist einfach eine zu liberale Lesung des Nehmens „versagt“ in dem, was zur Zeit ist [class.copy.elision]/3, die besagt, dass in dieser Situation

overload resolution to select the constructor for the copy is first performed as if the object were designated by an rvalue. If the first overload resolution fails or was not performed, [...], overload resolution is performed again, considering the object as an lvalue.

, dass die Resolution überlasten wird nicht scheitern; Es ist erfolgreich und wählt den Move-Konstruktor aus, der zufällig gelöscht wird. Das sollte das Ende der Sache sein.

Dies wurde gemeldet als bug 31025.

+0

@columbo keine Antwort? –

+0

@HBellamy Sag was? Ich habe meine Antwort entsprechend geändert. – Columbo

Verwandte Themen