Funktions-Template blockieren



  • Hallo

    Ich möchte, dass von einem Funktionstemplate nur bestimmte Spezialsierungen zugelassen sind. Ich hätte gern, dass bei Verwendung des normalen Templates gar nicht erst kompiliert werden kann. Kennt jemand eine bessere / elegantere Umsetzung als die hier?

    Hier mein Ansatz:

    struct invalid_byte_count
    {
    };
    
    template<size_t size>
    inline void Reverse(void *data)
    {
      // hier verschluckt sich der Kompiler
      invalid_byte_count test = data;
    }
    
    template<>
    inline void Reverse<2>(void *data)
    {
      std::swap(reinterpret_cast<char*>(data)[0], reinterpret_cast<char*>(data)[1]);
    }
    
    template<>
    inline void Reverse<4>(void *data)
    {
      std::swap(reinterpret_cast<char*>(data)[0], reinterpret_cast<char*>(data)[3]);
      std::swap(reinterpret_cast<char*>(data)[1], reinterpret_cast<char*>(data)[2]);
    }
    
    template<>
    inline void Reverse<8>(void *data)
    {
      std::swap(reinterpret_cast<char*>(data)[0], reinterpret_cast<char*>(data)[7]);
      std::swap(reinterpret_cast<char*>(data)[1], reinterpret_cast<char*>(data)[6]);
      std::swap(reinterpret_cast<char*>(data)[2], reinterpret_cast<char*>(data)[5]);
      std::swap(reinterpret_cast<char*>(data)[3], reinterpret_cast<char*>(data)[4]);
    }
    


  • Etwas kürzer: Du lässt den Rumpf der allgemeinen Funktion komplett weg - dann wird sich der Linker beschweren.

    Aber was ist überhaupt der Sinn dieser Funktion?



  • CStoll schrieb:

    Etwas kürzer: Du lässt den Rumpf der allgemeinen Funktion komplett weg - dann wird sich der Linker beschweren.

    Aber was ist überhaupt der Sinn dieser Funktion?

    Damit will ich von big endian nach little endian umwandeln und umgekehrt. Am liebsten hätte ich es eigentlich, wenn die Funktionen nur integrale Typen fressen würden. Momentan weiss ich nicht, wie ich das realisieren könnte.

    edit: ich meinte eigentlich eingebaute typen.





  • Wenn du nur 3 verschiedene Varianten - noch dazu mit jeweils unabhängiger Umsetzung - benötigst, ist ein Template wohl etwas übertrieben. Schreib dir einfach Überladungen für alle Typen, die du brauchst.



  • CStoll schrieb:

    Wenn du nur 3 verschiedene Varianten - noch dazu mit jeweils unabhängiger Umsetzung - benötigst, ist ein Template wohl etwas übertrieben. Schreib dir einfach Überladungen für alle Typen, die du brauchst.

    Naja, dann müsste ich ja für jeden Typ eine Überladung schreiben und dann noch für unsigned. Nicht unbedingt ein geringerer Aufwand.



  • Stefan schrieb:

    Damit will ich von big endian nach little endian umwandeln und umgekehrt. Am liebsten hätte ich es eigentlich, wenn die Funktionen nur integrale Typen fressen würden. Momentan weiss ich nicht, wie ich das realisieren könnte.
    edit: ich meinte eigentlich eingebaute typen.

    Hallo Stefan,

    mit boost ist es recht einfach:

    #include <string>
    #include <boost/utility/enable_if.hpp>
    #include <boost/type_traits.hpp>
    
    namespace reverse_details
    {
        template< unsigned N >
        void reverseN( char* p );
    
        template<> void reverseN< 2 >( char* p )
        {
            std::swap( p[1], p[0] );
        }
        template<> void reverseN< 4 >( char* p )
        {
            std::swap( p[3], p[0] );
            std::swap( p[2], p[1] );
        }
        // ...
    }
    template< typename T >
    typename boost::enable_if< typename boost::is_integral< T >, void >::type 
        Reverse( T& x )
    {
        reverse_details::reverseN< sizeof(T) >( reinterpret_cast< char* >( &x ) );
    }
    
    // Anwendung
        int a = 4;
        Reverse( a );
        string txt;
        //Reverse( txt ); // übesetzt nicht
    

    Mehr Info dazu gibt's in der boost-Hilfe zu integral_type und enable_if.

    Gruß
    Werner


Anmelden zum Antworten