= Operator in Template Klassen Limitieren



  • Ich habe einen Template Container mit einem = Operator. Das Kopieren eines Containers in einen anderen soll aber nur dann erlaubt sein wenn es sich nicht um Zeiger handelt. Mir ist dazu nur diese Lösung eingefallen.

    template<typename T_Type>
    class Container
    {
    private:
    
        template<typename T_Allow>
        class Allow
        {
        public:
            void allow()
            {};
        };
    
        template<typename T_Allow>
        class Allow<T_Allow*>
        {
        private:
            void allow()
            {
                #pragma message("operator= bei Zeigern nicht erlaubt")
            };
        };
    
    public:
    
        Container<T_Type>& operator=(const Container<T_Type> &rhs)
        {
            Allow<T_Type>::allow();
            //Kopierarbeiten
        };
    };
    

    Gäbe es noch eine andere bzw bessere Lösung um beim Aufruf des = Operators für bestimte Typen direkt beim Compilen einen Fehler hervorzurufen?



  • Xebov schrieb:

    Gäbe es noch eine andere bzw bessere Lösung um beim Aufruf des = Operators für bestimte Typen direkt beim Compilen einen Fehler hervorzurufen?

    Du verlässt Dich darauf, dass das pragma erst beim Instanziieren des Templates behandelt wird und nicht schon vorher. Das mag bei MSVC noch funktionieren, bei allen anderen Compilern wahrscheinlich nicht, da pragmas sowieso implementierungsabhängig sind.


  • Mod

    Vergiss #pragma oder such dir ein anderes Unterforum aus.

    template <typename T>
    class AssignHelper {};
    
    template <typename T>
    class AssignHelper<T*>
    {
    private:
        void operator=(AssignHelper&);
    };
    
    template<typename T>
    class Container : AssignHelper<T>
    {
    };
    

    Sofern der implizt deklarierte Zuweisungsoperator ausreicht.

    Muss der Zuweisungsoperator selbst definiert werden, z.B. so

    template<typename T>
    class Container
    {
        Container& operator=(const Container& rhs)
        {
            BOOST_STATIC_ASSERT( !boost::is_pointer<T>::value ); // oder
            int dummy[!boost::is_pointer<T>::value];dummy; // o.ä.
            ...
        }
    };
    


  • Oder simpel mit boost::disavle_if :

    template<typename T_Type>
    class Container
    {
    public:
    
        boost::disable_if<boost::is_pointer<T_Type>, Container<T_Type>&>::type //liefert Container<T_Type>& falls T_Type kein Pointer ist, sonst Compilererror
        operator=(const Container<T_Type> &rhs)
        {
            //Kopierarbeiten
        };
    };
    


  • Danke das disable_if sieht schon viel brauchbarer aus.



  • pumuckl, du brauchst hier noch ein typename :

    // Benötigte Boost-Header
    #include <boost/utility/enable_if.hpp>
    #include <boost/type_traits/is_pointer.hpp>
    
    template<typename T_Type> 
    class Container 
    { 
    public: 
        // hier
        typename boost::disable_if<boost::is_pointer<T_Type>, Container<T_Type>&>::type
        operator=(const Container<T_Type> &rhs) 
        { 
    
        }
    };
    

  • Mod

    pumuckl schrieb:

    Oder simpel mit boost::disavle_if :

    Allerdings ist der Operator kein Template, also gibt es auch kein SFINAE. Eine Funktionstemplate wiederum verhindert nicht die implizite Deklaration der normalen Operatorfunktion.



  • camper schrieb:

    pumuckl schrieb:

    Oder simpel mit boost::disavle_if :

    Allerdings ist der Operator kein Template, also gibt es auch kein SFINAE. Eine Funktionstemplate wiederum verhindert nicht die implizite Deklaration der normalen Operatorfunktion.

    und ich dachte immer Memberfunktionen und damit auch der op= von Klassentemplates sind automatisch auch Templates.
    MSVC schluckt das jedenfalls ohne zu meckern (was natürlich nicht unbedingt was heißt bei templates)



  • Danke für die Vorschläge hab mir alles mal angesehen. disable_if fällt für mich aus da ich lediglich den Copy Operator und Copy Construktor ausknipsen will für alle Zeiger Typen. Das Static_assert liefert schon ein ganz gutes Ergebniss. Schade nur das man einzellne Funktionen nicht einfach in Abhängigkeit der Parameter private/public machen kann.

    camper schrieb:

    Vergiss #pragma oder such dir ein anderes Unterforum aus.

    Was hat pragma bitte mit nem anderen unterforum zu tun?



  • The #pragma directives offer a way for each compiler to offer machine- and operating system-specific features [...] Pragmas are machine- or operating system-specific by definition, and are usually different for every compiler.

    (Quelle: MSDN)



  • Hab das Problem jetzt mit Vererbung gelöst.

    template<typename T>
    class ContainerBase
    {
    protected:
        //ctor
        //copy ctor
        //= operator
    };
    
    template<typename T>
    class Container:public ContainerBase<T>
    {
    public:
        //ctor
        //copy ctor
        //= operator
    };
    
    template<typename T>
    class Container<T*>:public ContainerBase<T*>
    {
    private:
        //copy ctor
        //= operator
    public:
        //ctor
    };
    

    Liefert genau das was ich wollte. Container mit Zeiegrn sind nicht kopierbar und die Fehlermeldungen sind etwas genauer als bei boost static_assert.

    Danke nochmal an alle für die Hilfe.


Anmelden zum Antworten