swap std :: unique_ptr mit Lambda als Deleter - GCC

8

Können wir ein Lambda als Deleter mit einem std :: unique_ptr verwenden? Genau genommen habe ich es mit clang ++ gemacht und es war glücklich, das zu tun.

Ich verwende std::swap , um zu std::unique_ptr<ObjType, decltyp(deleter)>; zu wechseln wo auto deleter = [](struct addrinfo* ptr){if (ptr != nullptr) {freeaddrinfo(ptr);} }; . Clangs Swap scheint keinen Kopierzuweisungsoperator zu benötigen, aber gcc's std :: swap, wie Sie in diesen Protokollen sehen können:

%Vor%

Was sagt der Standard? Kann ich diese beiden std :: unique_ptr wap? Sind sie ein Workaround? (Vielleicht das Lambda innerhalb einer std :: -Funktion einkapseln? ...)

Bearbeiten: Hier ist ein kleines Beispiel, das mehr oder weniger dasselbe sein sollte:

%Vor%

Der Fehler:

%Vor%     
Jeremy Cochoy 05.07.2013, 16:33
quelle

4 Antworten

3

Um auf Jonathan Wakelys Antwort zu erweitern:

Wenn Sie zu unique_ptr s wechseln, müssen Sie auch deren Deleter austauschen. Das Problem, das Sie sehen, läuft darauf hinaus: clang kann zwei Lambdas des gleichen Typs austauschen, gcc kann nicht (und der Standard erlaubt beides, wie Jonathan es zitiert). Demonstration:

%Vor%

Dieser Code funktioniert mit clang, kann aber nicht mit gcc kompiliert werden. (Und das ist in Ordnung.)

Darum passiert es.

Ich schlage Folgendes vor:

%Vor%

Beachten Sie, dass der Code sauberer und lesbarer wurde.

Wenn Sie das unbedingt mit lambdas lösen müssen, dann könnten Sie vielleicht etwas hackish wie folgt ausprobieren: Tauschen Sie nur die Zeiger, aber nicht die Löscher.

%Vor%

Obwohl dieser Code zu funktionieren scheint, mag ich ihn wirklich nicht. Ich schlage die erste Lösung vor, die keine Lambdas verwendet.

    
Ali 05.07.2013, 21:47
quelle
5

Das hat nichts mit unique_ptr oder tuple zu tun, Sie können den Fehler folgendermaßen reduzieren:

%Vor%

Das kompiliert mit Clang, aber schlägt mit G ++ fehl und gibt diesen Fehler an:

%Vor%

Der letzte C ++ 11-Standard sagt in [expr.prim.lambda] / 19:

  

Der mit einem Lambda-Ausdruck verknüpfte Schließungstyp hat einen gelöschten (8.4.3) Standardkonstruktor und einen Zuweisungsoperator für gelöschte Kopien. Es hat einen implizit deklarierten Kopierkonstruktor (12.8) und kann einen implizit deklarierten Move-Konstruktor haben (12.8).

Es liegt also am Compiler, ob der Typ zuweisbar ist oder nicht.

    
Jonathan Wakely 05.07.2013 23:14
quelle
2

Ich kann einen ähnlichen Fehler mit dem folgenden Code reproduzieren:

%Vor%

Entkommentieren Sie den Bewegungszuweisungsoperator und der Fehler verschwindet. Ich nehme an, dass gcc die Zuordnung von lambas nicht zulässt (ich benutze Version 4.7.2). Ändern Sie das Lambda in eine tatsächliche Funktion oder einen Funktor und Sie sollten in Ordnung sein.

    
pelletjl 05.07.2013 17:36
quelle
1

Wie sich herausstellt, können Sie es mit Lambdas lösen, solange sie in Funktionszeiger umgewandelt werden können (Lambdas, die nichts fangen).

%Vor%

Dennoch mag ich meine andere Lösung mit der Struktur besser. Es ist wahrscheinlich die effizienteste (dank Inlining), gefolgt von der hier vorgestellten Lösung. Das Übergeben eines schwergewichtigen std::function sieht für mich wie ein Overkill aus, wenn die Deleter-Implementierung wirklich einfach ist. Ob diese Leistungsüberlegungen wichtig sind, ist die Aufgabe des Profilers.

    
Ali 06.07.2013 13:27
quelle

Tags und Links