Verständnisfragen SFINAE
-
Hallo Hustbär,
danke für die Antworten. Punkt zwei war natürlich Quatsch, habe beim Rauslöschen ein Klammerpärchen übersehen.
Ich verstehe die decltype-Anweisungen nicht, zb.decltype( void(container.remove_if(std::forward<Predicate>(predicate))))
. Was für ein Konstrukt ist denn dervoid(container.remove_if(std::forward<Predicate>(predicate)))
Teil? Angenommen ich hätte nurdecltype(container.remove_if(std::forward<Predicate>(predicate))
, dann bezeichnet decltype den Rückgabetyp desremove_if
-Aufrufs. Aber wenn das noch invoid(...)
eingepackt wird verstehe ich das nicht mehr.
Hast du da vllt iwo nen Artikel, der das für Idioten erklärt?
-
void(...)
ist ein functional-style cast. Also einfach ein Ausdruck, der den Operanden (hier als Ellipse dargestellt) zuvoid
konvertiert, damit der Typ, dendecltype(void(...))
bezeichnet,void
ist. Das ist dieselbe Klasse von Ausdruck wiestring("asdf")
odervector{1, 2, 3}
. Der einzige Anlass für diesenvoid
Cast ist die Tatsache, dass der Rückgabewert der Funktion selbstvoid
sein muss.Um das ganze mal etwas kohärenter zu erklären: Wir haben eine Reihe von Methoden, um Elemente aus einem Container zu entfernen.
chooser
ist ein bekanntes Idiom, in welchem eine einfache Vererbungshierarchie (chooser<0> → chooser<1> → ...
) eingesetzt wird, um eine Rangfolge in der overload resolution aufzuerlegen. Die optimale Methode wird vom Argument des Typenchooser<10>
die minimale Anzahl an Vererbungsebenen hinaufsteigen (7) um zuchooser<3>
zu konvertieren.Allerdings ist die Instanz dieses (und der anderen spezialisierten) Funktionstemplates nur dann ein Kandidat, wenn der Ausdruck im
decltype(void(...))
wohlgeformt ist. Als erstes scheiden also alle Funktionstemplates aus, deren Deduktion aufgrund des Ausdrucks fehlerhaft ist. Dann wird (dank Symmetrie) die Funktion ausgewaehlt, deren Parameter die tiefste Vererbungsebene vonchoose
hat.In C++17 koennte man das etwas eleganter schreiben, naemlich mittels
if constexpr
undis_detected
.
-
Aaaaah, danke!
Den function-style cast kannte ich noch nicht, jetzt ergibt das alles Sinn.
-
@DocShoe
T(...)
ist im Prinzip das selbe wie((T)...)
-
Die ganzen vereinfachten Funktionen für den vollen Container, also sort(vec) anstatt sort(vec.begin(), vec.end()) etc. sollten im Standard festgelegt sein, damit nicht jeder den Mist selbst definieren muss... Sind wir mal ehrlich, wie oft musstet ihr schon Mal nur einen Teil eines Containers sortieren?
-
@HarteWare sagte in Verständnisfragen SFINAE:
Die ganzen vereinfachten Funktionen für den vollen Container, also sort(vec) anstatt sort(vec.begin(), vec.end()) etc. sollten im Standard festgelegt sein
Muss du halt eine ranges-Bibliothek wie range-v3 einbinden oder auf C++20 warten.
-
-
Ja ich freue mich auf C++20, GCC hat noch nicht mal C++17 ganz implementiert...
-
@HarteWare tatsächlich? Ich dachte eigentlich, dass inzwischen alle (GCC, Clang und MSVC) vollständigen C++17 support haben. Welche Features fehlen denn beim GCC?
-
@Unterfliege
laut der Liste ist nicht nur GCC noch nicht "fertig".
https://en.cppreference.com/w/cpp/compiler_support
-
@HarteWare sagte in Verständnisfragen SFINAE:
Die ganzen vereinfachten Funktionen für den vollen Container, also sort(vec) anstatt sort(vec.begin(), vec.end()) etc. sollten im Standard festgelegt sein, damit nicht jeder den Mist selbst definieren muss... Sind wir mal ehrlich, wie oft musstet ihr schon Mal nur einen Teil eines Containers sortieren?
der Aufruf von std::sort mit den Iteratoren ist jetzt aber auch nicht soooo der Zeitfresser... Da wäre mir eine socket-bibliothek im C++Standard wichtiger, als eine Sort-Funktion die statt 3 Parametern nur 2 braucht...
-
@It0101 sagte in Verständnisfragen SFINAE:
der Aufruf von std::sort mit den Iteratoren ist jetzt aber auch nicht soooo der Zeitfresser...
Es ist ja nicht nur sort. In den meisten Fällen operiere ich mit einem kompletten std::vector. Auch bei accumulate. Gut, bei lower_bound hat man öfter mal andere Grenzen. Aber sehr oft operiere ich doch auf dem ganzen Ding. Es ist auch nicht sooo der Zeitfresser,
vector<int>::const_iterator
in einer for-Loop zu schreiben. Dennoch istauto
wesentlich angenehmer. So auch hier. Von daher:Ich weiß nicht, was genau von range-v3 im Standard gelandet ist, aber ich fand auch Projections ziemlich gut.
-
@Unterfliege Naja das ist halt ein Rant von mir, weil ich mal gerne std::from_chars verwendet hätte und dann mein Compiler mich angemault hat.
Was mich auch etwas nervt: Sachen wie std::fstream etc. haben keinen c-tor für std::string_view...