std::basic_ifstream unsigned char und std::char_traits unsigned char



  • Ich versuche gerade einen input file stream zu benutzen, der auf unsigned char
    basiert und nicht auf chars, wie es bei dem std::ifstream typedef ist.
    Dafür habe ich mir meine char_traits Spezialisierung für unsigned char geschrieben.

    Nun habe ich eine Frage und ein Problem. Erstmal die Frage

    Wenn ich eine Spezialisierung für char_traits schreiben will, muss ich ja
    eigentlich den Namespace std erweitern, aber dass ist doch eigentlich vom
    Standard verboten. Wie kann ich das Problem umgehen?

    nun das Problem

    bei dem folgenden Code (ist ein bissel länger, muss aber leider sein 😞 )

    #include <string>
    #include <cstring>
    #include <fstream>
    
    namespace std {
      /*! \brief char_traits for unsigned char
          std::char_traits implementation for unsigned char
       */
      template< > struct char_traits<unsigned char> {
        //! data type for characters
        typedef unsigned char char_type;
        //! = operator
        static inline void assign(char_type &to,const char_type &from) {
          to=from;
        }
        //! data type for the integer representation
        typedef int int_type;
        //! convert from int_type to char_type
        static inline char_type to_char_type(const int_type &o) {
          return static_cast<char_type>(o);
        }
        //! convert from char_type to int_type
        static inline int_type to_int_type(const char_type &o) {
          return static_cast<int_type>(o);
        }
        //! == operator for int_type
        static inline bool eq_int_type(const int_type &o0,const int_type &o1) {
          return o0==o1;
        }
        //! == operator for char_type
        static inline bool eq(const char_type &o0,const char_type &o1) {
          return o0==o1;
        }
        //! < operator for char_type
        static inline bool lt(const char_type &o0,const char_type &o1) {
          return o0<o1;
        }
        /*! Moves n characters from the object pointed at by s1 into the object 
          pointed at by s2. The ranges of (s1,s1+n) and (s2,s2+n) may overlap.*/
        static inline char_type *move(char_type *s1,const char_type *s2, size_t n){
          return static_cast<char_type*>(memmove(s1,s2,n));
        }
        /*! Copies n characters from the object pointed at by s1 into the object 
          pointed at by s2. The ranges of (s1,s1+n) and (s2,s2+n) may not overlap*/
        static inline char_type *copy(char_type *s1,const char_type *s2,size_t n) {
          return static_cast<char_type*>(memcpy(s1,s2,n));
        }
        /*! Assigns one character value to n elements of a character array. 
            The value of a is assigned to n elements of s.*/
        static inline char_type *assign(char_type *s,size_t n,const char_type &a){
          return static_cast<char_type*>(memset(s,a,n));
        }
        /*! Compares n values from s1 with n values from s2. Returns 1 if s1 is 
            greater than s2, -1 if s1 is less than s2, or 0 if they are equal.
         */
        static inline int compare(const char_type *s1,const char_type *s2,
                      size_t n) {
          return memcmp(s1,s2,n);
        }
        //!Returns the length of a null terminated character string pointed at by s
        static inline size_t length(const char_type *s1) {
          const char_type *ptr=s1;
          while(*ptr) ++ptr;
          return ptr-s1;
        }
        /*!Looks for the value of a in s. Only n elements of s are examined. 
          Returns a pointer to the matched element if one is found. Otherwise 
          returns a pointer to the n element in s.*/
        static const char_type *find(const char_type *s,int n,const char_type &a) {
          for(int i=0;i<n;++i) {
        if(s[i]==a)
          return s+i;
          }
          return s+n;
        }
    
        //! offset in streams
        typedef streamoff off_type;
        //! position in streams
        typedef streampos pos_type;
        //! multi-byte stream state
        typedef mbstate_t state_type;
    
        //! End-Of-File
        static inline int_type eof() { return EOF; }
        //! Returns a value which is not equal to the end-of-file value.
        static inline int_type not_eof(const int_type &i) {
          return i==EOF ? !i : i;
        }
      };
    }
    
    int main() {
      std::basic_ifstream<unsigned char> i;
    }
    

    erhalte ich folgende Linker Fehler

    g++ -Wall -W -std=c++98 -o ucharfile ucharfile.cc 
    /tmp/ccs3bRNJ.o(.gnu.linkonce.t._ZNSt13basic_filebufIhSt11char_traitsIhEE9underflowEv+0xf): In function `std::basic_filebuf<unsigned char, std::char_traits<unsigned char> >::underflow()':
    : undefined reference to `std::basic_filebuf<unsigned char, std::char_traits<unsigned char> >::_M_underflow_common(bool)'
    /tmp/ccs3bRNJ.o(.gnu.linkonce.t._ZNSt13basic_filebufIhSt11char_traitsIhEE5uflowEv+0xf): In function `std::basic_filebuf<unsigned char, std::char_traits<unsigned char> >::uflow()':
    : undefined reference to `std::basic_filebuf<unsigned char, std::char_traits<unsigned char> >::_M_underflow_common(bool)'
    collect2: ld returned 1 exit status
    

    was mache ich falsch? Wie kann ich mir einen std::basic_ifstream unsigned char
    richtig erstellen

    [ Dieser Beitrag wurde am 06.07.2003 um 17:18 Uhr von kingruedi editiert. ]

    [ Dieser Beitrag wurde am 06.07.2003 um 17:18 Uhr von kingruedi editiert. ]



  • Warum mußt Du dan den Namensraum std erweitern?
    Du kannst die traits-klasse doch auch einfach außerhalb des Namesraums std schreiben. Beim instaziieren mußt Du dann halt den template-Parameter explizit angeben.

    Mit Deinem eigentlichen Problem kann ich Dir leider auch nicht helfen. Da wirst Du wohl auf Hume warten müssen.



  • Wenn ich eine Spezialisierung für char_traits schreiben will, muss ich ja
    eigentlich den Namespace std erweitern, aber dass ist doch eigentlich vom
    Standard verboten

    Nicht ganz. Spezialisierungen sind im Namensraum std erlaubt, solange sie für einen eigenen Typen sind. Dazu zählt unsigned char aber natürlich nicht.

    Insgesamt hast du hier verloren. Es gibt keine zufriedenstellende Antwort aus sicht von Standard-C++. Es sei denn du findest: "geht nicht" zufriendenstellend.

    Ansonsten: [url=http://groups.google.de/groups?hl=de&lr=&ie=UTF-8&oe=UTF-8&frame=right&th=1c27919350c9ddb7&seekm=88c4053e.0301201510.5bf19d4c%40posting.google.com#link1]
    klärender Thread in CLC++M[/url]

    [ Dieser Beitrag wurde am 07.07.2003 um 12:33 Uhr von HumeSikkins editiert. ]



  • naja, ich kann das jetzt auch anders lösen. Ist aber irgend wie dumm, dass das nicht geht (eigentlich hätte ich erwartet, dass der Standard schon direkt so was hat 😞 )


Anmelden zum Antworten