Gleiche Template-Spezialisierung für const und non-const Funktion



  • Hallo zusammen,

    muss ich in folgendem Code zwei verschiedene Versionen für die const und non-const getter schreiben oder gibt es einen Weg, dass es auf beide matcht?

    #include <iostream>
    
    struct foo1{
    	int bar() const{ return 1;};
    };
    
    struct foo2{
    	int bar;
    };
    
    struct foo3{
    	std::string bar(){ return "";};
    };
    
    struct foo4{
    	std::string bar;
    };
    
    template<typename T>
    struct field_type;
    
    template<typename R, typename S>
    struct field_type<R (S::*)>{
    	typedef R type;
    };
    
    template<typename R, typename S>
    struct field_type<R (S::*)() const>{
    	typedef R type;
    };
    
    /*template<typename R, typename S>
    struct field_type<R (S::*)()>{
    	typedef R type;
    };*/
    
    template<typename U, typename V, typename W>
    struct field_info_type;
    
    template<typename U, typename V>
    struct field_info_type<U, V, V (U::*)> {
    	static const int type = 2;
    };
    
    template<typename U, typename V>
    struct field_info_type<U, V, V (U::*)() const> {
    	static const int type = 1;
    };
    
    /*template<typename U, typename V>
    struct field_info_type<U, V, V (U::*)()> {
    	static const int type = 1;
    };*/
    
    int main(){
    	std::cout << field_info_type<foo1, field_type<decltype(&foo1::bar)>::type, decltype(&foo1::bar)>::type << std::endl;
    	std::cout << field_info_type<foo2, field_type<decltype(&foo2::bar)>::type, decltype(&foo2::bar)>::type << std::endl;
    	std::cout << field_info_type<foo3, field_type<decltype(&foo3::bar)>::type, decltype(&foo3::bar)>::type << std::endl;
    	std::cout << field_info_type<foo4, field_type<decltype(&foo4::bar)>::type, decltype(&foo4::bar)>::type << std::endl;
    }
    

    Ich möchte an den Zeilen in der main nichts ändern, da ich den Code später durch ein Makro generieren lassen möchte. (Oder halt einheitlich ändern)

    Was ich aber absolut nicht verstehe:
    Warum ist die Ausgabe von dem Code?

    1
    2
    2
    2

    Also ich hätte einen Compilerfehler erwartet... Aber der nicht konstante getter passt in meine Funktion für den Member-Pointer?
    Warum das?

    Gruß,
    XSpille


  • Mod

    XSpille schrieb:

    Aber der nicht konstante getter passt in meine Funktion für den Member-Pointer?

    Der konstante Getter tut das auch, nur hast dem Compiler ja eine Spezialisierung dafür gegeben, so dass das nicht auffällt.

    Wird ein Templateparameter der Form

    T U::*
    

    mit einem Memberfunktionszeiger gefüttert, so wird T als entsprechender Funktionstyp deduziert.

    field_type<decltype(&foo1::bar)>::type // wäre int() const, wenn es die Spezialisierung für const-Memberfunktionen nicht gäbe
        field_type<decltype(&foo2::bar)>::type // ist int
        field_type<decltype(&foo3::bar)>::type // ist std::string()
        field_type<decltype(&foo4::bar)>::type // ist std::string
    

    Ältere Compiler sind dafür bekannt, diese Deduktion nicht immer korrekt durchzuführen.



  • Danke Camper 🙂

    eine Folgefrage habe ich noch:
    Wie nennt man die Rückgabe von foo3? Also ich meine das std::string()
    Wenns geht auch auf englisch 🙂


  • Mod

    function (taking no arguments) returning std::string?



  • camper schrieb:

    function (taking no arguments) returning std::string?

    Ok... Ich dachte da gibts nen speziellen Ausdruck 🙂



  • nullary function?


Anmelden zum Antworten