boost :: remove_const do it youself



  • Hi@ all

    ich habe eine template function: in etwa so:

    template<typename TValue>
    void( TValue& val )
    {
       //work with TValue AND the non const type of TVal
    }
    

    problem ist jetzt, das ich in der Function nur den Type von TValue kenne, z.b. fuer const int, ist der eben auch const int. Ich brauche aber den non-const typen. In Boost giebt es dafuer remove_const. Leider kommt boost nicht in frage.

    ich habe also angefangen meine eigenen kleinen Traits zu schreiben:

    template< typename T, bool bIsConst >
    struct TypeContainer
    {
    	typedef T Type;
    };
    
    template<>
    struct TypeContainer<const int, false>
    {
    	typedef int Type;	
    };
    
    template<>
    struct TypeContainer<const double, false>
    {
    	typedef double Type;
    };
    
    template<>
    struct TypeContainer<const std::wstring, false>
    {
    	typedef std::wstring Type;
    };
    
    template< typename T >
    struct ConstTraits
    {
    	enum{ IS_CONST = 0 };
    	typedef TypeContainer<T, true>::Type Type;
    	typedef TypeContainer<T, false>::Type NonConstType;
    };
    
    template<>
    struct ConstTraits<const>
    { 
    	enum{ IS_CONST = 1 };
    	typedef TypeContainer<T, true>::Type Type;
    	typedef TypeContainer<T, false>::Type NonConstType;
    };
    

    haesslich ist daran, dass ich den TypeContainer fuer jeden typen implementieren muss (was nicht weiter schlimm ist, weil ich sowieseo nur basic typen unterstuetze), auch wenn es nur 3 Zeilen sind ;). Boost remove_const sieht aber im Vergliech dazu fast noch komplizierter aus (hab mir noch nicht die muehe gemacht da komplett durchzusteigen). Irgendwelche Ideen fuer eine simple elegante loesung?

    Sorry fuer das bloede Beispiel am Anfang. Die genauere Erklaerung warum ich das remove_const brauche ist etwas komplizierter und ich wollte erstmal die Abkuerzung versuchen...

    Danke und Viele Gruesse aus dem sonnigen Knoxville / Tennessee


  • Administrator

    Auf die Schnelle und ohne Spezialfälle:

    #include <iostream> 
    #include <typeinfo> 
    
    template<typename T>
    struct RemoveConst
    {
    	typedef T Result;
    };
    
    template<typename T>
    struct RemoveConst<const T>
    {
    	typedef T Result;
    };
    
    int main() 
    {
    	std::cout << typeid(RemoveConst<int>::Result).name() << std::endl;
    	std::cout << typeid(RemoveConst<const int>::Result).name() << std::endl;
    
    	std::cin.get();
    
    	return 0;
    }
    

    Aber wieso willst du kein Boost verwenden? Naja...

    Grüssli



  • Aber wieso willst du kein Boost verwenden? Naja...

    das hat mit wollen nichts zu tun, "duerfen" waere passender.... 🙂

    Naja, bei uns giebt es einen Tool - Validierungsprozess. D.h. um eine Bibbliothek oder Tool verwenden muss man erst belegen ob es Sinn macht (Endlose Diskussionen/Meetings/Dokumete etc.....).
    Auf der Einen Seite ist es Gut, weil es Wildwuchs verhindert, in diesem speziellen Fall nervt es.....

    Danke fuer Deinen Schnellschuss, werd mal testen, ob ich das im VS6 hier mit unseren Komilersettings so umsetzen kann.



  • Hi, hab gerade mal schnell im VS6 ausprobiert:

    template< class TValue >
    void addValue( TValue& lhs )
    {
    	typedef RemoveConst<TValue>::Result NonConstType;
    	typedef NonConstType & NonConstRefType;
    
    	std::cout << typeid( NonConstType ).name() << std::endl;//correct : type is int
    	std::cout << typeid( NonConstRefType ).name() << std::endl;//strange : type is int const& ....
    
    	NonConstRefType refIValue = const_cast< NonConstRefType >( lhs );
    	refIValue = 22;//error lhs is const.....
    }
    
    //in main
    const int iLhs = 0;
    addValue( iLhs );
    

    erstmal war ich erstaunt, wie gut Dein Beispiel funktioniert hat : ich war mir fast sicher, dass ich das so auch schon probiert habe 😉
    Irgendwie scheint es aber nicht fuer const referenzen zu funktionieren (leider mein Anwendungsfall). Es wundert mich schon, warum der Compiler fuer

    std::cout << typeid( RemoveConst<const int&>::Result ).name() << std::endl;//strange : type is int const& ....
    

    int const& ausspuckt.....

    Danke fuer Deine Hilfe



  • Warum copy 'n pastest du boost::remove_const nicht einfach in dein Projekt, natürlich mit Vermerk, dass du es aus der boost-Bibliothek kopiert hast?



  • Tippgeber schrieb:

    ...

    Weil du ungefähr 30 andere boost Dateien dann auch kopieren musst ? Boost Dateien inkludieren wiederrum auch andere Boost Dateien, also viel Spaß?



  • dann muesste ich beim code review auch alles erklaeren, darum geht es ja bei einer bibliotheksvalidierung 😉

    boost::remove_const ist auch alles in allem recht complex: ich war selber ganz ueberrascht....
    Ehrlich gesagt kann ich das problem auch anders loesen, aber dann wuerde es zu lasten der const correctness meiner klassen gehen. Mir faellt es halt schwer solche probleme liegen zu lassen.
    Ich dachte auch, dass es simpel umzusetzen geht mit der Einschreankung auf standard datentypen (POD + Strings + enums), aber dem is wohl nicht so.....



  • TheBigW schrieb:

    Irgendwie scheint es aber nicht fuer const referenzen zu funktionieren (leider mein Anwendungsfall).

    Dann spezialisierst du die Geschichte eben auch für Referenzen und const Referenzen 🙂


  • Administrator

    TheBigW schrieb:

    Danke fuer Deinen Schnellschuss, werd mal testen, ob ich das im VS6 hier mit unseren Komilersettings so umsetzen kann.

    Hmmm, die Sache scheint echt hinderlich zu sein, wenn ihr noch den VS6 einsetzt 😃

    Aber wie pumuckl gesagt hat, probier einfach noch die Spezialiserung auf T const& und T& für Referenzen und jeweils ein typedef T& Result dazu. Könnte funktionieren, sogar auf dem VS6.

    Grüssli



  • VS6 -> ich hasse es : http://support.microsoft.com/kb/240866#appliesto

    hatte ganz vergessen: keine partielle spezialisierung!!!
    Ich hab gerade mal im Codeblocks ausprobiert, wie schoen das eigentlich funktioniert.
    Damit hat sich wohl ein vernuenftige Loesung erledigt, Trotzdem Danke euch allen.

    Wie schoen koennte die Welt mit einem Vernuenftigen Kompiler sein.......


  • Administrator

    Das sind aber keine partiellen Spezialisierungen 😉
    Meine Spezialisierungen waren alle vollständig.

    Grüssli



  • ...aber leider nicht fuer Referenzen im VS6 🙂 : ich braeuchte eine Spezialierung fuer referenzen:

    //I wonder if this syntax is somehow standard conform????
    struct RemoveConst<const &>
    {
        typedef T Result;
    };
    

    leider nimmt der compiler die so nicht, auch wenn es sich kompilieren laesst und

    template< typename T >
    struct RemoveConst<const T&>...
    

    laesst sich nicht kompilieren (im VS6 im g++ gehts...), weil C2989, womit ich wieder bei meinem Link mit partieller Spezialisierung waere...

    Wie gesagt Dein Beispiel war super und der folgende Tip von pumuckl mit der spezialisierung hat super funktioniert im g++ aber im VS6 leider nicht......



  • Wieso benutzt du VS6?!?!? Was 'n das für ein laden wo du arbeitest..



  • ist 'ne groessere "Firma" ;). Vergleichbar mit den Dilbert comics.... Restriktionen haben halt positive und negative Seiten...


Log in to reply