2016-02-14 17 views
9

Ich spielte mit dem Lambda "überladen" wie dargestellt here, und kam schnell zu dem Punkt, wo ich es bequem finden würde, spezialisierte Lambda-Verschlüsse zu erstellen. So war ich zum ersten Mal Trial-and-error'ing ein bisschen mit meiner vielversprechendsten StudieC++ spezialisieren einen Lambda für einen bestimmten Typ

seine
auto call_for_vector = [] template<typename T> (std::vector<T>) {}; 

jedoch ein später Blick auf den cppreference zeigte, dass weder dieses noch ähnliche Konstrukte scheinen von der Norm erlaubt zu werden.

Aus welchem ​​Grund werden solche Spezialisierungen nicht unterstützt?

Ich weiß, dass man dieses Verhalten mit SFINAE erhalten kann, aber dann ist es weniger lesbar, schwerer zu schreiben und fehleranfälliger. Natürlich kann man simpy auch eine Klasse mit einem geeigneten operator() schreiben, aber das ist soo C++ 03 :-)



Welche Verwendung für eine solche Syntax wäre ?:

ein Beispiel, würde dies für eine einfache Lambda „Überlast“, wie im folgenden Code erlaubt

template <class F1, class F2> 
struct overload_set : F1, F2 
{ 
    overload_set(F1 x1, F2 x2) : F1(x1), F2(x2) {} 
    using F1::operator(); 
    using F2::operator(); 
}; 

template <class F1, class F2> 
overload_set<F1,F2> overload(F1 x1, F2 x2) 
{ 
    return overload_set<F1,F2>(x1,x2); 
} 

auto f = overload(
     [](auto&& x){ std::cout<<"call by default"<<std::endl;}, 
     [] template<typename T>(std::vector<T>){std::cout<<"call for vector"<<std::endl;} 
     ); 

One dieses Verhalten erhalten kann zB mit SFINAE Basis auf die Technik in this answer, aber wieder ... das ist scheiße.

Gibt es eine einfache Problemumgehung für SFINAE, um bestimmte Überladungen zu erhalten?

+0

Nun, ich denke, dass Sie mit std :: function famillar sind, die die Art ist, mit dauerhaften Funktionen zu arbeiten. Ich denke, Lambdas sind flüchtig in dem Sinne, dass der Standard nicht möchte, dass Sie sie speichern, wie es ist –

+0

@David Haim: das obige funktioniert auch nicht mit 'std :: function', da es eine bestimmte Signatur benötigt. – davidhigh

+0

können Sie std :: function, 'template std :: function templatetize –

Antwort

2

Diese Art der Codierung mag zunächst überflüssig erscheinen, aber es gibt einige nette Eigenschaften, die wir nutzen können. In Bezug auf den Beitrag, den du erwähnst, plante ich einen Teil 2, wo ich einen hübschen Weg von prüfen würde, ob ein Typ ein bestimmtes Mitglied (Funktion oder Daten) hat. Angenommen, Sie möchten nach einer serialize Mitgliedsfunktion suchen. anstatt komplizierte Mechanismen der Verwendung entdeckte ich, es wird so einfach wie:

auto hs = overload( 
    [ ](auto&& x) -> decltype(x.serialize(2), std::true_type{}) { 
     return{}; },  // ^^ this guy ^^ 
    [ ](...) -> std::false_type { return {}; }); 

demo

die Besonderheiten der standardese Evolution here gefunden werden kann, aber der Grund gab ich dies für eine solche Syntax zu befürworten ist was hatten wir es gehabt haben, könnte die oben sein erweitert zu unter „überlastet“ generic lambdas partielle Ordnung erlauben:

auto do_something = overload( 
    [ ]<class X>(shared_ptr<X> x) -> decltype(x.serialize(2), std::true_type{}) { 
     /*do something specific for shared ptrs of X */ return{}; },  
    [ ]<class X>(X& x) -> decltype(x.serialize(2), std::true_type{}) { 
     /*do a generic operation for other types that have serialize*/return{}; },  
    [ ](...) -> std::false_type { /*do nothing*/ return {}; }); 
+2

ah ja, so sfinae, aber die moderne (und kürzere) Art und Weise ... – davidhigh

+0

könnten Sie den Verweis auf Ihre andere Antwort hinzufügen? Ich würde es dann einen Haken geben, und dann schließen wir diesen Faden in einer großen Feier als Duplikat. – davidhigh

+0

@davidhigh Ich habe keine andere Antwort, ich habe gerade eine ähnliche q –

Verwandte Themen