Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

Das Gurke

Community-Fossil

  • »Das Gurke« ist der Autor dieses Themas

Beiträge: 1 996

Wohnort: Pinneberg

Beruf: Schüler

  • Private Nachricht senden

1

29.08.2008, 15:41

[C++] Zu doof um eine Templatemethode zu spezialisieren

Ich und Templates werden wohl nie ganz Freunde werden ... Ich habe, grob zusammengefasst folgenden Code:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
        //! Returns a key as a specific type whilst performing the conversion via a stringstream.

        /*! This will only work for C++ basic types, not for user defined ones! */
        template<typename T>
        T getKeyAs(const std::string& section, const std::string& key)
        {
            // Making sure the field exists

            if (!hasKey(section, key))
            {
                // No key or no section?

                if (!hasSection(section))
                    throw (std::out_of_range("Could not find section \"" + section + "\""));
                else
                    throw (std::out_of_range("Could not find key \"" + key + "\""));
            }

            // Convert the value

            std::istringstream stream(mSettings[section][key]);
            T ret;
            stream >> ret;

            return (ret);
        }
Dieser code sucht aus einer geschachtelten Map (für Sektionen und einzelne Wert) einen Wert raus, jagt ihn durch einen stringstream und erlaubt es mir so, die meisten grundlegenden C++ Typen sehr komfortabel aus meiner Config Klasse zu ziehen.

Dieses System versagt aber (naheliegenderweise), wenn ich einen boolschen Wert auslesen möchte, da ich boolsche Werte als string in der .cfg hinterlege. Also in etwa so:

Quellcode

1
2
[MySection]
somebool = true


Jetzt könnte ich natürlich auf 0 und 1 ausweichen, aber ich find die "Textvariante" schon schöner. Also wollte ich das Template folgendermaßen spezialisieren:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
template<>
        bool getKeyAs<bool>(const std::string& section, const std::string& key)
        {
            // Retrieve the value of the key and transform it to lowercase

            std::string value = getKey(section, key);
            std::transform(value.begin(), value.end(), value.begin(), tolower);

            // Everything nonzero or "true" means true

            return (value != "0" || value == "true");
        }


Nur leider wird diese Spezialisierung nie aufgerufen. Google spuckt mir wenn ich nach C++ Template Method Specialisation suche immer nur relativ fortgeschrittene Themen aus (Partial specialisation etc).

Aber ich vermute fast, dass der Fehler irgendwo winzigklein in meinem Code steckt ...

Edit: Autsch, das tut er ... Der gcc kompiliert das nichtmal ^^

David_pb

Community-Fossil

Beiträge: 3 886

Beruf: 3D Graphics Programmer

  • Private Nachricht senden

2

29.08.2008, 15:43

Wie rufst du das Template denn auf?
@D13_Dreinig

drakon

Supermoderator

Beiträge: 6 513

Wohnort: Schweiz

Beruf: Entrepreneur

  • Private Nachricht senden

3

29.08.2008, 15:43

Wie rufst du es auf?

EDIT:
Zu langsam.. ^^

Du könntest doch auch einfach TRUE und FALSE suchen und ersetzen. Wäre eine andere Variante.

Das Gurke

Community-Fossil

  • »Das Gurke« ist der Autor dieses Themas

Beiträge: 1 996

Wohnort: Pinneberg

Beruf: Schüler

  • Private Nachricht senden

4

29.08.2008, 15:44

C-/C++-Quelltext

1
mDebug = cfg.getKeyAs<bool>("WoRD", "debug");


Edit: Klar könnte ich das. Dann müsste ich das aber ausserhalb der cfg Klasse wieder auf lowercase transformieren und dann dort vergleichen. Schön ist was anderes ^^

5

29.08.2008, 15:48

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
template<>
bool getKeyAs(const std::string& section, const std::string& key)
{
    // Retrieve the value of the key and transform it to lowercase

    std::string value = getKey(section, key);
    std::transform(value.begin(), value.end(), value.begin(), tolower);

    // Everything nonzero or "true" means true

    return (value != "0" || value == "true");
}
Devil Entertainment :: Your education is our inspiration
Der Spieleprogrammierer :: Community Magazin
Merlin - A Legend awakes :: You are a dedicated C++ (DirectX) programmer and you have ability to work in a team? Contact us!
Siedler II.5 RttR :: The old settlers-style is comming back!

Also known as (D)Evil

David_pb

Community-Fossil

Beiträge: 3 886

Beruf: 3D Graphics Programmer

  • Private Nachricht senden

6

29.08.2008, 15:48

Zitat von »"Das Gurke"«

C-/C++-Quelltext

1
mDebug = cfg.getKeyAs<bool>("WoRD", "debug");


So ist das richtig! Sollte funktionieren.
@D13_Dreinig

Das Gurke

Community-Fossil

  • »Das Gurke« ist der Autor dieses Themas

Beiträge: 1 996

Wohnort: Pinneberg

Beruf: Schüler

  • Private Nachricht senden

7

29.08.2008, 15:51

Hmm, mit Devilopers Methode komm ich mit dem VC++ 2005 Compiler zum gewünschten Ergebnis. Dann meckert aber der gcc:

Quellcode

1
2
3
./../WoRD - Shared/Config.h:65: error: explicit specialization in non-namespace scope `class WoRD::Config'
./../WoRD - Shared/Config.h:67: error: `getKeyAs' is not a template function
./../WoRD - Shared/Config.h:67: error: invalid function declaration

drakon

Supermoderator

Beiträge: 6 513

Wohnort: Schweiz

Beruf: Entrepreneur

  • Private Nachricht senden

8

29.08.2008, 15:52

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class foo
{
public:
    template<class T>
    T get ()
    {
        std::cout << "something" << std::endl;
        return T();
    }

    template<>
    bool get ()
    {
        std::cout << "bool" << std::endl;
        return true;
    }
};

..

     foo f;
     f.get<int> ();
     f.get<bool> ();


Das ist ja in etwa das. Und das sollte so gehen.

Das Gurke

Community-Fossil

  • »Das Gurke« ist der Autor dieses Themas

Beiträge: 1 996

Wohnort: Pinneberg

Beruf: Schüler

  • Private Nachricht senden

9

29.08.2008, 15:56

Ich glaub mich tritt grad ein Pferd ... Im Debugmodus (bzw Debug Build) vom Visual Studio funktioniert die von drakon und Deviloper vorgeschlagene Lösung wunderbar. Der gcc (3.4.5) weigert sich allerdings, dieses Konstrukt zu kompilieren (siehe Fehlermeldung weiter oben).

Im Releasemodus wird weiterhin die "nicht spezialisierte" Methode aufgerufen. Rebuild hat auch nix gebracht.

Ich schau lieber nochmal selber ein wenig, der Fehler ist ja so verquer, dass er quasi bei mir liegen muss ^^

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

10

29.08.2008, 15:59

verrat mal etwas mehr vom umfeld. sind das member einer klasse? ist die klasse selber ein template!?

vielleicht solltest du auch mal deinen gcc updaten :p

Werbeanzeige