Concepts in der Praxis



  • Hey,
    ich habe mich in letzter Zeit etwas mit den C++17-Concepts beschäftigt. Dabei kam mir die Überlegung, wie Concepts es ermöglichen wollen, die Templateargumente auf Kompatibilität von in der Funktion benutzten Templatevariablen zu überprüfen?
    Also z. B.:

    template <typename T>
    concept bool C = requires (T a, int b)
    {
        { a.func(b) } -> void; 
    };
    
    struct A
    {
        void func(int b) { UNUSED(b); }
        int a{0};
    };
    
    void doSomething(C param)
    {
        std::map<decltype(param), decltype(param)> map;
        param.func(5);
        map.insert(std::make_pair(param, param));
    }
    
    int main()
    {
        doSomething(A{});     
    }
    

    Bei diesem Beispiel hat man wieder das Problem, dass std::map einen <-Operator verlangt.



  • Ich sehe es als Defizit von C++, wenn bei Funktionsaufrufe Errors in Code auftauchen können, den ich selber nicht implementiert habe. Und wenn ich bei Concepts Funktionen beachten müsste, welche in meiner Funktion aufgerufen werden, würde das doch die Concepts ziemlich aufblähen und es würde zu Problemen führen wenn in Funktionsaufrufen in meiner Funktion irgendwelche zusätzlichen Abhängigkeiten hinzu kämen (wenn wir das obigere Bsp. nehmen und z.B. in der insert-Funktion von std::map plötzlich noch der >-Operator verlangt werden würde) oder nicht?


  • Mod

    Ab einem gewissen Punkt wird LWG auch map mit einigen Contraints versehen. Dann kannst du mittels eines type contraints überprüfen, ob die Spezialisierung std::map<a, b> auch gültig ist (wobei ein type constraint IIRC die Spezialisierung per se nicht instantiiert, man müsste also auf e.g. einen Member zugreifen).

    Edit: Zu deinem zweiten Post: Wenn du für eine Funktion eine Reihe von constraints angeben willst, dann doch nur, um sie zu überladen? Dann sollten das aber relativ wenige sein, da du nur zu einem bestimmten Maße einschränkend sein willst. Sehr genaue Details brauchst du nicht zu überprüfen, sie würden Overload resolution nicht behilflich sein. E.g. für dein Beispiel einfach requires LessThanComparable<decltype(param)> angeben.



  • Aufpassen:
    T in map muss nicht LessThanComparable sein wenn man einen compare-Functor mit angibt.

    Man muss bei Concepts sehr aufpassen, dass man nicht zu viel einschränkt.



  • Das muss überhaupt nicht LessThanComparable sein. Die Standardvergleichsfunktion ist doch std::less . Die Vergleichsfunktion muss ein Konzept erfüllen, nicht das Element: Compare(std::declval<T>(), std::declval<T>()) muss "convertible to bool" oder so sein.



  • Erstmal danke an alle.

    Arcoth schrieb:

    Ab einem gewissen Punkt wird LWG auch map mit einigen Contraints versehen. Dann kannst du mittels eines type contraints überprüfen, ob die Spezialisierung std::map<a, b> auch gültig ist

    Meinst du das Concept von std::map wiederverwenden?

    Oder hast du mir da evtl. ein Beispiel?

    Shade Of Mine schrieb:

    Aufpassen:
    T in map muss nicht LessThanComparable sein wenn man einen compare-Functor mit angibt.

    Man muss bei Concepts sehr aufpassen, dass man nicht zu viel einschränkt.

    Danke, wusste ich noch nicht.


  • Mod

    TyRoXx schrieb:

    Das muss überhaupt nicht LessThanComparable sein.

    Doch?Ich entsinne mich von map<decltype(param), decltype(param)> gesprochen zu haben, nicht von irgendetwas allgemeinerem.


Anmelden zum Antworten