uni_cast?



  • Hi,

    gibt es so eine art UNICODE-Cast in C++?

    Ich möchte meine Programme in ANSI und in UNICODE-Varianten veröffentlichen, dafür habe ich nun sehr viel mit einem eigenen TEXT-Makro gearbeitet und es funktioniert auch alles einwandfrei! 🙂

    Jedoch gibt es diverse Funktionen die einen char* erwarten und andere wiederum umbedingt einen wchar_t* 😞

    jetzt dachte ich mir, da müsste es doch evtl sowas geben?

    dest_datentyp test = uni_cast<dest_datentyp>(source_datentyp);
    

    Gibt es da soetwas das genau so aufgebaut ist wie die anderen C++ casts? ich habe von Templatedesign leider nicht sehr viel ahnung 😞 😞



  • Hi,

    Es gibt was zum konvertieren:

    #include <iostream>
    #include <locale>
    int main()
    {
      char str[100] = "Hello World";
      wchar_t wstr[100];
      std::use_facet< std::ctype<wchar_t> >( std::locale("C") ).widen(str,str+100,wstr);
      std::wcout << wstr << std::endl;
    }
    

    // Edit: Fixed Typo



  • die manuelle konvertierung kenn ich, aber wie macht man daraus einen cast? 😮 wie schon gesagt, ich kenn mich mit templates nicht aus und ich glaube das man die dafür braucht?



  • ich hab mal vor kurzem so einen cast geschrieben, aber das grenzt eher an einen großen hack. ich kopier dir den code mal raus

    #include <locale>
    #include <string>
    
    #include <boost/type_traits.hpp>
    namespace utility{
    	namespace privat{
        //the class Converter chooses the right function whhich does the conversion
    		//there are 5 cases which have to be handled different:
    		//
    		//Type->AnotherType first uses narrow than widden, dataloss can occur
    		//Type->char uses narrow
    		//char->Type uses widden
    		//char->char no conversion
    		//Type->Type no conversion
    
    		//conversion type->type
    		template<class To,class From>
    		struct Converter{
    
    			static std::basic_string<To> convert(const std::basic_string<From>& input){
    				return Converter<To,char>::convert(Converter<char,From>::convert(input));
    			}
    
    			static To convertChar(From input){
    				return Converter<To,char>::convertChar(Converter<char,From>::convertChar(input));
    			}
    		};
    
    		//conversion char->type
    		template<class To>
    		struct Converter<To,char>{
    			static std::basic_string<To> convert(const std::string& input){
    				To* widen = new To[input.size()];
    
    				std::use_facet<std::ctype<To> > (std::locale()).widen(&*input.begin(), &*input.end(), widen);
    
    				std::basic_string<To> output(widen);
    				delete[] widen;
    
    				return output;
    			}
    			static To convertChar(char input){
    				return std::use_facet<std::ctype<To> > (std::locale()).widen(input);
    			}
    		};
    
    		//conversion type->char
    		template<class From>
    		struct Converter<char,From>{
    			static std::string convert(const std::basic_string<From>& input){
    				char* narrow = new char[input.size()];
    
    				std::use_facet<std::ctype<From> > (std::locale()).narrow(&*input.begin(), &*input.end(), narrow);
    
    				std::string output(narrow);
    				delete[] narrow;
    
    				return output;
    			}
    			static char convertChar(From input){
    				return std::use_facet<std::ctype<From> > (std::locale()).narrow(input);
    			}
    		};
    
    		//when both types are the same, no conversion is needed
    		template<class Char>
    		struct Converter<Char,Char>{
    			static const std::basic_string<Char>& convert(const std::basic_string<Char>& input){
    				return input;
    			}
    			static Char convertChar(Char input){
    				return input;
    			}
    		};
    		//specialisation for <char,char> prevents ambigouity
    		template<> struct Converter<char,char>{
    			static const std::basic_string<char>& convert(const std::basic_string<char>& input){
    				return input;
    			}
    			static char convertChar(char input){
    				return input;
    			}
    		};
    
    		//ConvertHelper has to differ between the 4 possible forms of the
    		//template paramter "from": single sign,pointer,basic_string and char array.
    		//Function templates doesnt work here because the compiler cannot
    		//differ between them
    
    		//when From is a pointer(cstring),it must be converted into a string
    		template<class To,class From,bool>
    		struct ConvertHelper{
    			typedef std::basic_string<To> returnType;
    
    			static returnType convert(From input){
    				//get the unqualified nonpointer type 
    				//example const char*->char
    				//this is needed for basic_string
    				typedef 
    				typename boost::remove_const<
    					typename boost::remove_pointer<
    						typename boost::remove_const<From>::type
    					>::type
    				>::type InnerFrom;
    
    				std::basic_string<InnerFrom> str(input);
    
    				return Converter<To,InnerFrom>::convert(str);
    			}				
    		};
    
    		//From is a normal char
    		template<class To,class From>
    		struct ConvertHelper<To,From,false>{
    
    			typedef To returnType;
    
    			static returnType convert(From str){
    				return Converter<To,From>::convertChar(str);
    			}				
    		};
    
    		//From is a std::basic_string
    		template<class To,class From>
    		struct ConvertHelper<To,std::basic_string<From>,false>{
    
    			typedef std::basic_string<To> returnType; 
    
    			static returnType convert(const std::basic_string<From>& str){
    				return Converter<To,From>::convert(str);
    			}
    		};
    
    		//from is a char array
    		template<class To,class From,int i>
    		struct ConvertHelper<To,From[i],false>{
    
    			typedef std::basic_string<To> returnType;
    
    			typedef typename boost::remove_const<From>::type InnerFrom;
    
    			static returnType convert(const std::basic_string<InnerFrom>& str){
    				return Converter<To,InnerFrom>::convert(str);
    			}
    		};
    	}
    
    	//the function itself
    	template<class To,class From>
    	typename privat::ConvertHelper<To,From,boost::is_pointer<From>::value>::returnType 
    	char_convert(const From& input){
    		return privat::ConvertHelper<To,From,boost::is_pointer<From>::value>::convert(input);
    	}
    }
    


  • iiiiih boost! nee lass mal. Bevor mein Programm total aus den Näten platzt lasse ich das lieber. 😞



  • das was da aus boost benutzt wird ist nur minimal und das kannst du auch einfach nachprogrammieren.

    MfG



  • Dir zu liebe, ohne Garantie, iplementierungen für is_pointer,remove_const und remove_pointer:

    template<class T>
    struct is_pointer
    {
        enum{value=false};    //static const bool, können aber meines wissens nach nicht alle compiler
    };
    
    template<class T>
    struct is_pointer<T*>
    {
        enum{value=true};
    };
    
    template<class T>
    struct remove_const
    {
        typedef T type;
    };
    
    template<class T>
    struct remove_const<const T>
    {
        typedef T type;
    };
    
    template<class T>
    struct remove_pointer
    {
        typedef T type;
    };
    
    template<class T>
    struct remove_pointer<T*>
    {
        typedef T type;
    };
    

    Das sollte dein Programm kein byte größer machen, da nix instanziert wird.



  • @ness:
    wie benutzt man das?!?!?! 😮



  • Wenn du z.b. immer sicherstellen willst das du den grund typen bekommst: ( Ohne const, pointer usw )

    template < typename Type >
    struct always_int
    {
      typedef typename remove_const< typename remove_pointer< typename remove_const< Type >::type >::type >::type type;
    };
    
    std::string bool_to_str( bool val )
    {
      return ( val ? "true" : "false" );
    }
    
    int main()
    {
      std::cout << bool_to_str( typeid(always_int< const int * const >::type) == typeid(int) ) << std::endl;
      std::cout << bool_to_str( typeid(always_int< const int *       >::type) == typeid(int) ) << std::endl;
      std::cout << bool_to_str( typeid(always_int< const int         >::type) == typeid(int) ) << std::endl;
      std::cout << bool_to_str( typeid(always_int<       int * const >::type) == typeid(int) ) << std::endl;
      std::cout << bool_to_str( typeid(always_int<       int *       >::type) == typeid(int) ) << std::endl;
      std::cout << bool_to_str( typeid(always_int<       int         >::type) == typeid(int) ) << std::endl;
    }
    
    Output:
    true
    true
    true
    true
    true
    true
    


  • Hi,

    hab durch zufall diesen Thread gefunden und bin auch sehr an diesem "cast" interessiert. Jedoch habe ich den Code von Otze ausprobiert, doch er geht nicht 😞 Er bringt das Programm zum absturz 😞

    Weiß einer warum? 😕



  • hab durch zufall diesen Thread gefunden und bin auch sehr an diesem "cast" interessiert.

    Verarsch doch die Leute nicht. Du bist doch der Threadstarter.



  • Ich versteh ehrlich gesagt nicht, warum ihr diese Unmengen von Code postet.

    Was ist mit

    mbtowc()
    wctomb()
    mbstowcs()
    wcstombs()

    oder unter Windows auch

    WideCharToMultiByte()
    MultiByteToWideChar()

    Ist natürlich alles C und umständlich zu nutzen, aber hat für mich immer funktioniert.



  • evilissimo schrieb:

    std::string bool_to_str( bool val )
    {
      return ( val ? "true" : "false" );
    }
    

    Das brauchst du nicht wirklich. Dafuer kannst du auch das Flag boolalpha setzen ;).

    mfg
    v R



  • pZy schrieb:

    Ist natürlich alles C und umständlich zu nutzen, aber hat für mich immer funktioniert.

    weil es nicht plattformunabhaengig ist?


Anmelden zum Antworten