Lambda als Templateparameter für Validierung



  • Guten Tag,

    ich möchte gerne eine Option -Klasse erstellen, welche einen beliebigen Wert beinhalten kann. Der Haken dabei: jeder Wert kann einen bestimmten Wertebereich annehmen. Daher dachte ich mir, dass ich mit Lambdas arbeiten kann. Das ist mein erster Versuch auf diesem Gebiet.

    Optimale Vorstellung meinerseits wäre bspw. das hier:

    class SomeClass
    {
    public:
    	void Blub()
    	{
    		intValue_ = 20;
    		doubleValue_ = 4.2;
    	}
    
    	void HighlyFrequentedFunction()
    	{
    		std::cout << "Result is: " << (intValue_ * doubleValue_) << "\n";
    	}
    
    private:
    	Option<int, [] (const int &source, int &value) -> bool {
    		value = source;
    		return true;
    	}> intValue_;
    
    	Option<double, [] (const double &source, double &value) -> bool {
    		if (source < 2.0 || source > 5.0) return false;
    		value = source * 2;
    		return true;
    	}> doubleValue_;
    };
    
    int mai(int argc, char *argv[])
    {
    	SomeClass test;
    	test.Blub();
    
    	for (int i = 0; i < 20; ++i) test.HighlyFrequentedFunction();
    
    	return 0;
    }
    

    Mein Ansatz ist somit dieser hier:

    template<typename T, typename Setter>
    class Option
    {
    public:
    	Option()
    		: setter_(Setter)
    	{
    	}
    
    	/* operator= to be done, ruft dann setter mit value_ als value-Parameter auf */
    	/* noch irgendwas, um intValue_ oder doubleValue_ direkt verwenden zu können */
    
    private:
    	T value_;
    	std::function<bool(const T &source, T &value)> setter_;
    };
    

    Ausgabe (von hier):

    prog.cpp: In constructor ‘Option<T, Setter>::Option()’:
    prog.cpp:9:19: error: expected primary-expression before ‘)’ token
    prog.cpp: At global scope:
    prog.cpp:39:3: error: type/value mismatch at argument 2 in template parameter list for ‘template<class T, class Setter> class Option’
    prog.cpp:39:3: error:   expected a type, got ‘<lambda closure object><lambda(const int&, int&)>{}’
    prog.cpp:45:3: error: template argument 2 is invalid
    

    Da ich neu bin, weiß ich nicht, ob ich etwas falsch mache (Syntaxmäßig oder auch vom Design her) oder ob es schlicht und ergreifend nicht so schön geht.

    Wie würdet ihr das machen? Wo liegen meine Fehler? Bin dankbar für Hilfe! 🙂



  • theliquidwave schrieb:

    ich möchte gerne eine Option -Klasse erstellen, welche einen beliebigen Wert beinhalten kann. Der Haken dabei: jeder Wert kann einen bestimmten Wertebereich annehmen.

    Versteh ich net. Also weder den ersten Wunsch, noch den Haken. Erklär mal bitte etwas genauer. 😉



  • Okay. Ich möchte eine einfache Möglichkeit bieten, eine Optionsvariable von beliebigem Datentyp zu erstellen. Später einmal sollen dann Benutzereingaben (also DAU-Eingaben) in die Setter-Funktion gegeben werden. Jede Optionsvariable kann natürlich andere Werte annehmen. Beispiel: es macht keinen Sinn der Variable "FootstepsPerSecond" auf 2000 zu setzen. Die Eingabe in die Setterfunktion wäre dann:

    source: 2000
    value: Referenz auf die value_-Variable aus der Option-Klasse

    Ich hoffe, dass es nun besser erklärt ist.



  • Und warum willst du das als Template-Parameter der Klasse übergeben? Ist es so wichtig, dass die Range zum Typ gehört?
    Falls nein: Einfach eine std::function<...> im Konstruktor geben lassen. (Und den Template-Parameter für die Range entfernen.)
    Falls ja: Zeile 6 ändern zu : setter_(Setter()) und als Template-Parameter gibst du jetzt einen Typen an, bei dem der operator () überladen ist.



  • Naja, dann ist das ganze ja nicht mehr schön. Wenn ich wieder extra ein struct/class dafür erstellen muss, ist das alles nicht mehr an einem Platz. Ich habe genau gehofft, mit den Templates zu erreichen, dass ich eine Optionsvariable an genau einem Platz erstellen kann (eben der Klassendeklaration). Wenn ich nun wieder was in den Konstruktor und/oder andere Structs auslagern muss entfällt die Möglichkeit...



  • Das sollte mit einer Lambda ohne Capture-List eigentlich funktionieren, da diese implizit in einen Funktionszeiger konvertierbar sind. In etwa so:

    template
    <
        typename T,
        bool (* setter) (T&, T)
    >
    struct Option
    {
        Option& operator = (T value)
        {
            setter(val_, value);
            return *this;
        }
    
        operator T () const
        {
            return val_;
        }
    
    private:
        T val_;
    };
    
    Option<int, [] (int& out, int val)
        {
            if(val < 42)
                return false;
    
            out = val;
            return true;
        }> x;
    

    Code ungetestet.


Anmelden zum Antworten