Typauflösung bei template



  • Folgendes Problem :

    struct convert_ex
    {
    	template<typename other_string_type,typename result_string_type>
    	result_string_type operator()(const other_string_type &Arg) const
    	{
    		return result_string_type(Arg.begin(),Arg.end()) ;
    	}
    };
    
    string Str1="test" ;
    convert_ex aConverter ;
    string Str2=aConverter(Str1) ;
    

    Der Compiler meldet mir den Fehler "error: no match for call to `(convert_ex) (std::string&)'"
    Der Compiler müsste doch dies auflösen können, oder liege ich hier komplett falsch.

    Besten Dank für eure Bemühungen.


  • Mod

    Wo soll result_string_type herkommen?



  • Der Ausdruck "string Str2=aConverter(Str1) ; " sollte doch dem Compiler sagen was ich will ?



  • case schrieb:

    Der Ausdruck "string Str2=aConverter(Str1) ; " sollte doch dem Compiler sagen was ich will ?

    Nein, zumal Rückgabewerte nicht zwangsweise ausgewertet werden müssen.


  • Mod

    asc schrieb:

    case schrieb:

    Der Ausdruck "string Str2=aConverter(Str1) ; " sollte doch dem Compiler sagen was ich will ?

    Nein, zumal Rückgabewerte nicht zwangsweise ausgewertet werden müssen.

    string Str2=aConverter(Str1) ;
    

    ist kein Ausdruck, sondern eine Definition. Der initialisierende Ausdruck darin ist

    aConverter(Str1)
    

    und hieraus kann der Rückgabetyp nicht ermittelt werden. Eine direkte Deduktion des Rückgabetyps erfolgt nur bei Konvertierungsoperatoren - klar, denn hier ist ja die Konvertierung in einen bestimmten Zieltyp überhaupt erst der Grund für den Funktionsaufruf.



  • Ok, überzeugt.
    Dann muss ich mein Problem anders an gehen.
    Trotzdem danke..



  • du musst den result-Typ in irgendeiner Weise mitgeben, und zwar entweder als Argument (direkt oder indirekt) oder explizit als Templateparameter angeben. Beispiele:

    Expliziter templateparameter bei der Funktion

    struct convert_ex
    {
        template<typename result_string_type, typename other_string_type> //beachte: result_type zuerst, damit man den zweiten parameter weglassen kann
        result_string_type operator()(const other_string_type &Arg) const
        {
            return result_string_type(Arg.begin(),Arg.end()) ;
        }
    };
    
    /*...*/
    string Str2=aConverter.operator()<string>(Str1); //eklig, macht den nutzen in der Schreibweise mit op() zunichte
    

    Expliziter Templateparameter beim struct

    template <class result_string_type>
    struct convert_ex
    {
        template<typename other_string_type> 
        result_string_type operator()(const other_string_type &Arg) const
        {
            return result_string_type(Arg.begin(),Arg.end()) ;
        }
    };
    
    /*...*/
    convert_ex<string> aConverter;
    string Str2=aConverter(Str1);
    MyString Str3 = aConverter(Str1); // FEHLER: convert_ex<string> kann nicht in MyString konvertieren, ein ganz klarer Nachteil!
    

    Ermitteln des Typs aus einem zusätzlichen Argument:

    struct convert_ex
    {
        template<typename result_string_type, typename other_string_type> 
        result_string_type& operator()(const other_string_type &Arg, result_string_type& res) const
        {
            res = result_string_type(Arg.begin(),Arg.end()) ;
            return res;
        }
    };
    
    /*...*/
    string Str2;
    aConverter(Str1, Str2); //Nachteil: keine initialisierung von Str2 sondern eine Zuweisung. Str2 muss bereits bestehen.
    

    über einen Tag:

    template <typename string_type>
    struct StringTypeTag {};
    
    struct convert_ex
    {
        template<typename result_string_type, typename other_string_type> 
        result_string_type& operator()(const other_string_type &Arg, StringTypeTag<result_string_type>) const
        {
            return result_string_type(Arg.begin(),Arg.end()) ;
        }
    };
    
    /*...*/
    string Str2=aConverter(Str1, StringTypeTag<string>());
    

    Am Einfachsten wäre es wohl als freie Funktion, das wäre von allem etwas:

    template<typename result_string_type, typename other_string_type> //beachte: result_type zuerst, damit man den zweiten parameter weglassen kann
    result_string_type ConvertString(const other_string_type &Arg)
    {
      return result_string_type(Arg.begin(),Arg.end()) ;
    }
    
    /*...*/
    string Str2 = ConvertString<string>(Str1);
    


  • Danke pumuckl,

    Das bringt mich einen guten Schritt vorwärts.


Anmelden zum Antworten