C++ "template-Argument konnte nicht hergeleitet werden."

Spartaner117

Lt. Commander
Registriert
Feb. 2005
Beiträge
1.299
Hi,

im Moment sitz ich an einer Klassenfunktion, die mir aus einer Map zu einem bestimmten Key den passenden Value liefert. Die Values sind alle als string gespeichert, aber es wäre praktisch sie korrekt auszugeben, also bspw. den String "false" als ein bool false.
Das ist soweit kein Problem, nur:
Um einen variablen Rückgabewert zu haben, hab ich mich für eine Template-Klasse entschlossen. Die zickt aber mit folgender Meldung:
template-Argument für "T" konnte nicht hergeleitet werden.
Ich hab noch nicht so viel mit Templates gemacht, und hab nach knapp einer Stunde Grübeln wirklich keine Idee woran es liegen könnte.

Der Code:

Code:
template<class T> T CConfig::ShowConfig(string key, char mode)
{
    T retval;
    map<string, string>::iterator i;
    i = ConfigValues.find(key);
    if(i != ConfigValues.end())
    {
        switch(mode)
        {
        case 'b':
            {
                if(i->second == "true")
                    retval = true;
                else
                    retval = false;
            }break;
        case 's':
            {
                retval = i->second;                
            }break;
        case 'i':
            {
                retval = atoi((i->second).c_str())
            }break;
        }
    }
    else
        retval = "key_not_found";

    return retval;
}

Vielen Dank in voraus.
 
Das wird so nicht funktionieren, denn die Typen in Templates müssen schon während dem Kompilieren bekannt sein (es wird für jeden benötigten Typ Code erzeugt), bei dir ergibt sich der Typ aber erst zur Laufzeit. Außerdem kannst du in C++ Methoden nicht nur mittels des Rückgabewerts überladen.

Eine mögliche Lösung wären verschiedene Funktionen für die verschiedenen Typen ( ShowConfigString, ShowConfigInteger, ...).
 
Du musst den Typ in diesem Fall beim Aufruf angeben, also z.B. config.ShowConfig<int>( ...);

Wie Raechar schon sagte - und die Fehlermeldung auch :) - nur aus dem Rückgabewert einer Funktion kann das Template-Argument nicht hergeleitet werden.

Außerdem finde ich den "mode"-Schalter sehr gruselig. Der Ziel-Typ ergibt sich ja durch das Template-Argument. Die Typsicherheit, die man durch das Template gewinnt, geht damit sofort wieder verloren.
Probier doch mal das hier. :) Wenn du Fragen hast, fragen.

Code:
#include <sstream>
#include <stdexcept>

template<class T> T CConfig::ShowConfig(const string& key) const
{
    T retval = T();
    map<string, string>::const_iterator i = ConfigValues.find(key);
    if(i != ConfigValues.end())
    {
        istringstream iss( it->second);
        if( iss >> retval) {
            return retval;
        }
        else {
            throw runtime_error( "cannot convert " + it->second);
        }
    }
    else {
        throw runtime_error( "key " + key + " not found");
    }
}

Der Ansatz hat die "Schwäche", dass T Default-konstruierbar sein muss. Außerdem ist eben genau der Template-Typ nicht aus dem Aufruf ableitbar.

Das ließe sich z.B. durch so eine Signatur erreichen:
Code:
template<class T> void CConfig::ShowConfig(const string& key, T& retval) const

Außerdem ist der Name "ShowConfig" evtl. irreführend, vielleicht eher sowas wie GetConfigValue.
 
Zuletzt bearbeitet:
Zurück
Oben