R-Werte und L-Werte anders verteilen und sfinae verwenden, um eine Option zu deaktivieren

9

Ich möchte eine Funktion drop_if implementieren. Bei einem unären Prädikat und einem sequentiellen Container wird ein Container desselben Typs zurückgegeben, der nur die Elemente enthält, die nicht dem Prädikat entsprechen.

Wenn der Eingabecontainer ein r-Wert ist, sollte er in-Place arbeiten, andernfalls erstellen Sie eine Kopie. Dies wird erreicht, indem Sie in die entsprechende Version in namespace internal versenden. Die r-Wert-Version sollte deaktiviert werden, wenn der value_type des Containers nicht überschrieben werden kann - wie zum Beispiel std::pair<const int, int> - auch wenn der Container ein r-Wert ist.

Der folgende Code funktioniert erwartungsgemäß mit dem clang und den aktuellen Versionen von gcc (& gt; = 6.3).

%Vor%

Allerdings nicht kompilieren auf MSVC ++ und GCC 6.2 , weil sie sich für std::is_assignable :

nicht korrekt verhalten %Vor%

Siehe Antwort auf diese Frage und Bibliotheksfehlerbericht 2729 .

Ich möchte, dass es mit verschiedenen Containern und mit verschiedenen Arten von Objekten, z.B. std::vector<double> , std::map<int, std::string> usw. Der Fall std::map (mit einem anderen Einfüger ) ist die Situation, in der ich habe das Problem mit value_types von std::pair<const T, U> gefunden.

Haben Sie irgendwelche Ideen, wie der Versand / sfinae geändert werden könnte, um auch für MSVC ++ (ver. MSVC ++ 2017 15.2 26430.6 in meinem Fall) und für GCC 6.2 nach unten zu arbeiten?

    
Tobias Hermann 14.06.2017, 10:43
quelle

4 Antworten

2

Das Problem scheint zu sein, dass MSVC std::pair<const T, U>::operator= nicht SFINAE deaktiviert ist. Es existiert, selbst wenn es nicht funktioniert.

Wenn Sie also feststellen, ob es existiert, existiert es. Wenn Sie es ausführen, kann es nicht kompiliert werden.

Wir können das umgehen. Aber es ist ein Workaround.

%Vor%

anschauliches Beispiel und anderes Live-Beispiel .

Ich habe auch Ihre SFINAE-Dispatching auf tagbasierte Dispatching geändert.

Andere Typen mit defekter operator= Deaktivierung benötigen möglicherweise auch can_self_assign Spezialisierungen. Bemerkenswerte Beispiele können tuple<Ts...> und vector<T,A> und ähnliche enthalten.

Ich weiß nicht, wann und ob Compiler wo operator= "nicht existieren" müssen, wenn es in std types nicht funktionieren würde; Ich erinnere mich, dass es an einem Punkt für std::vector nicht erforderlich war, aber ich erinnere mich auch an einen Vorschlag, der solche Anforderungen hinzufügt.

    
Yakk 14.06.2017, 16:12
quelle
0

Sie sagen nicht, welche Version des Visual C ++ - Compilers Sie verwenden, aber haben Sie versucht, die nachfolgende Rückkehrsyntax zu verwenden?

Mit anderen Worten, ersetzen Sie dies:

%Vor%

mit so etwas?

%Vor%

Der Visual C ++ - Compiler wurde nach und nach in C ++ 11/14/17 hinzugefügt. Ich habe mit der Erstellung der MPL-Vorlage gekämpft und musste einige Dinge bearbeiten, die funktionieren sollten, aber nicht.

Ich gebe zu, das ist ein bisschen eine Vermutung, aber Sie könnten es versuchen.

    
Joe 14.06.2017 13:14
quelle
0

Wenn Sie möchten, dass Ihr Code speziell für Container mit tupelähnlichen Objekten bestimmt ist, könnten Sie das tun (brutal, aber mit älteren Versionen von gcc und MSVC):

%Vor%

[Live-Demo]

    
W.F. 14.06.2017 13:18
quelle
0

Schönes Ergebnis, bis diese Änderungen behoben sind, biete ich meine Lösung für diesen Eckfall an.

%Vor%

Dies führt nur eine is_assignable Spezialisierung für den Paartyp ein, wie es in dem Fehlerbericht . Die andere Sache, die ich hinzugefügt habe, ist std::is_rvalue_reference zu verhindern, wenn von den Aufrufen auf lvalue Referenzen (in Ihrer Lösung wurde es durch eine Fehlersubstitution in Container::value_type deaktiviert, die fehlschlägt, wenn Container ist vector<...>& .

    
Yuki 14.06.2017 16:17
quelle