2009-03-15 6 views
22

Wie kann ich der STL-Implementierung erlauben, meine benutzerdefinierten Typen aufzunehmen? Auf MSVC gibt es eine Klasse std::tr1::hash, die ich unter VerwendungWie std :: tr1 :: Hash für benutzerdefinierte Typen zu erweitern?

namespace std 
{ 
    namespace tr1 
    { 
     template <> 
     struct hash<MyType> 
     { ... }; 
    } 
} 

teilweise spezialisieren können, aber das ist der empfohlene Weg? Funktioniert das auch mit der Implementierung von GCC? Für boost::hash reicht es, eine freie Funktion size_t hash_value (const MyType&) bereitzustellen, gibt es etwas Ähnliches für die TR1-Implementierung?

+0

Gibt es eine Möglichkeit, std :: hash für benutzerdefinierte Typen mit privaten Kopie Konstruktoren zu erweitern? Gibt es auch eine Möglichkeit, es mit einem Operator() zu erweitern, der anstelle von val einen konstanten Wert annimmt? –

+0

Was ist das Problem mit der Template-Spezialisierung? Sie nehmen keine Kopie Ihres Objekts (Sie übergeben es durch Referenzen), also kein Problem - und der Operator() nimmt eine Konstante ref oder Wert, was auch immer Sie wollen. Sehen Sie sich Phil Nashs Antwort an, die das Objekt als const ref. – Anteru

Antwort

4

Ja, das wird auch für GCC funktionieren. Ich benutze es in einem größeren Projekt und es funktioniert ohne Probleme. Sie können auch eine eigene benutzerdefinierte Hashing-Klasse für die TR1-Container angeben, aber es wird angegeben, dass std :: tr1 :: hash <> die Standard-Hashing-Klasse ist. Spezialisiert auf benutzerdefinierte Typen scheint dies der natürliche Weg zu sein, die Standard-Hashing-Funktionalität zu erweitern.

3

Da Sie nicht std Bibliothek Namespace hinzufügen, aber nur die Spezialisierungen, dann ist es vollkommen in Ordnung.

Wenn Sie einen allgemeineren Hashing-Ansatz (zum Beispiel Hash für die Tupel im Allgemeinen) bereitstellen möchten, dann werfen Sie einen Blick auf Boost Fusion. Here is a simple example, die für die meisten Fälle funktionieren werden (wahrscheinlich mit Ausnahme für Tupel von Tupeln)

21

Ich habe versucht, die genaue Syntax, dies zu tun mit den ungeordneten assoziativen Containern zu arbeiten (auch GCC verwenden, da die OP war frage) und triff diese Frage.

Leider ging es nicht auf die Ebene der Details, die ich wollte. Wenn ich durch die gcc-Header gucke, wie sie die Standard-Hash-Funktionen implementiert haben, funktioniert es. Im Hinblick auf den Mangel an Beispielen (zumindest zum Zeitpunkt des Schreibens) auf der Bahn Ich dachte, das so gut ein Ort sein würde, wie jeder mein eigenes Beispiel zu schreiben (was ich Arbeiten mit GCC bestätigen kann):


namespace std { namespace tr1 
{ 
    template <> 
    struct hash<MyType> : public unary_function<MyType, size_t> 
    { 
     size_t operator()(const MyType& v) const 
     { 
      return /* my hash algorithm */; 
     } 
    }; 
}} 

(Hinweis gibt sind zwei Namespaces hier - das ist nur meine Konvention verschachtelte Namensräume für Kollabieren)

0

Der folgende Codeausschnitt zeigt, wie std::tr1::unordered_map zu Mapping boost::const_string<char> zu void* analog zu spezialisieren, wie std::string gehasht wird.

#include <boost/const_string/const_string.hpp>  
typedef class boost::const_string<char> csc; 

namespace std 
{ 
namespace tr1 
{ 
template <> 
struct hash<csc> { 
public: 
    size_t operator()(const csc & x) const { 
     return std::_Hash_impl::hash(x.data(), x.size()); 
    } 
}; 
} 
} 

typedef std::tr1::unordered_map<csc, void*> Map; 
typedef Map::value_type Dual; ///< Element Type. 
Verwandte Themen