Template-Funktion für void foo(bar&) und void foo(const bar&)



  • Hallo zusammen,

    ich habe eine Template-Funktion mit einem Template-Parameter. Aus diesem Template-Parameter möchte ich mir eine Typ-Information holen.
    Wenn das übergeben Objekt const ist, dann wird ja auf dem Objekt eine entsprechende const-Funktion aufgerufen, ansonsten eine nicht-const-Funktion. In der Regel unterscheidet sich der Rückgabe-Typ ja um ein const.
    Wenn ich diesen Wert ja zwischenspeichern will, weiß ich nicht, ob es const ist oder nicht...
    Wie löse ich sowas am elegantesten?

    #include <iostream>
    #include <string>
    
    template<typename T>
    class Foo{
    public:
    	typedef T type;
    	T& get(){return t;}
    	const T& get() const {return t;}
    
    private:
    	T t;
    };
    
    template<typename T>
    static void print(T& t){
    	std::cout << "no const" << std::endl;
    }
    
    template<typename T>
    static void print(const T& t){
    	std::cout << "const" << std::endl;
    }
    
    template<typename F>
    void bar(F& f){
    	typedef typename F::type type;
    	type& t = f.get(); // Hier ist das Zwischenspeichern in einer Variable natürlich unnötig, aber in meinem komplexen Szenario benötige ich es
    	print(t);
    }
    
    int main(){
    	Foo<std::string> foo1;
    	bar(foo1);
    	const Foo<std::string>& foo2 (foo1);
    	bar(foo2);
    
    }
    

    Verständlicherweise krieg ich hier ein:

    test.cpp: In function 'void bar(F&) [with F = const Foo<std::basic_string<char> >]':
    test.cpp:36:10:   instantiated from here
    test.cpp:28:18: error: invalid initialization of reference of type 'type&' from expression of type 'const std::basic_string<char>'
    

    Ich progge C++0x, deswegen dachte ich an auto als Rückgabe-Typ, jedoch riecht es (denke ich) nach einem gcc-Bug:

    auto t = f.get();
    

    no const
    no const

    Also meine Idee wäre:

    template<typename T, typename T2>
    struct const_info{
    	typedef T2 type;
    };
    
    template<typename T, typename T2>
    struct const_info<const T, T2>{
    	typedef const T2 type;
    };
    
    typedef typename const_info<F, type>::type fixed_type;
    	fixed_type& t = f.get();
    

    no const
    const

    Geht es auch einfacher/sauberer oder einen entsprechenden boost-type-trait?
    Das struct verfügt natürlich wegen Wiederverwendbarkeit (Name des typedef) über zwei Template-Parameter, sonst natürlich auch mit einem Template-Parameter möglich...

    Gruß,
    XSpille



  • XSpille schrieb:

    Ich progge C++0x, deswegen dachte ich an auto als Rückgabe-Typ, jedoch riecht es (denke ich) nach einem gcc-Bug:

    auto t = f.get();
    

    Das ist kein Bug, sondern einfach eine normale Variable. Wenn du eine Referenz drauß machen möchtest, solltest du auto& schreiben.[/quote]

    Zum type_trait: ein is_const<typename remove_reference<F>::type> sollte es bringen.
    Du könntest t natürlich auch mit einem decltype(f.get()) t = f.get() initialisieren 😉



  • Danke pumuckl!

    Aber warum hat man bei der Verwendung von auto keine Referenz?
    Ich hätte den Rückgabe-Typ der Funktion erwartet...

    Ich werde zukünftig wohl decltype(f.get()) favorisieren...
    👍



  • XSpille schrieb:

    Aber warum hat man bei der Verwendung von auto keine Referenz?

    Wie würdest du dann eine Non-Reference definiteren wollen, die mit der Reference-Rückgabe einer Funktion initialisiert wird? Dann lieber mit auto& explizit ne Referenz draus machen.



  • Eine Frage habe ich doch noch...

    pumuckl schrieb:

    Zum type_trait: ein is_const<typename remove_reference<F>::type> sollte es bringen.

    Wie bringt mich der boolsche Wert bei einem typedef weiter?



  • -- Empty Post --


Anmelden zum Antworten