Template-Spezialisierung (Speicherverbrauch ermitteln)
-
Ich möchte eine Funktion schreiben, die mir den ungefähren Speicherverbrauch eines Objekts zurückgibt. Für triviale Typen t wird einfach sizeof(t) zurückgegeben:
template <class T> typename std::enable_if<std::is_trivial<T>::value, size_t>::type memory(const T& obj) { return sizeof(obj); }Für std::deque könnte die Implementierung so aussehen:
template <class U> size_t memory(const std::deque<U>& obj) { size_t sum = sizeof(obj); for (const U& u: obj) { sum += memory(u); } return sum; }Der berechnete Wert ist nicht exakt, aber für meine Zwecke reicht das aus. Mein Problem ist nun, dass der Compiler die Definition der memory-Funktion manchmal nicht "findet":
template <DimType DIMENSION, class T> class QuadLeafManager { public: struct FileInterval { //... } } template <DimType DIMENSION, class T> size_t memory(const typename QuadLeafManager<DIMENSION, T>::FileInterval& fint) { return sizeof(fint); }In der Überladung von memory(QuadLeafManager) wird memory(std::vector<FileInterval>) aufgerufen:
error: no matching function for call to 'memory(const External::QuadLeafManager<4u, float>::FileInterval&)' sum += memory(u); // <- dies ist der Aufruf in memory(std::vector<T>)Möglicherweise ist mein Ansatz schon verkehrt. Am liebsten hätte ich die Funktion standardmäßig als sizeof(...) definiert und sie bei Bedarf (std::vector, usw.) überladen. Wenn ich das richtig verstanden hab, kann man Funktionstemplates nicht partial spezialieren.
Wäre es besser memory() als Klasse zu deklarieren, in etwa so:
template <class T> struct Memory { static size_t get(const T& t) { return sizeof(t); } }; template <class U> struct Memory<std::vector<U>> { static size_t get(const std::vector<U>& v) { size_t sum = sizeof(v); for (const U& u: v) { sum += Memory<U>::get(u); } return sum; } };Der Aufruf kann dann aber etwas nervig sein, da man immer den Type angeben muss:
Memory<std::vector<int>>::get(xyz);Wie implementiert man mein Vorhaben am Besten?
-
Du musst schon angeben, was in welchem Namespace liegt. Und was hat
dequemit dem Problem zu tun, wenn es umvectorgeht?
-
Ramanujan schrieb:
template <class T> typename std::enable_if<std::is_trivial<T>::value, size_t>::type memory(const T& obj) { return sizeof(obj); }Ich nehme mal an, dieses Template befindet sich im globalen Namensraum
Ramanujan schrieb:
Mein Problem ist nun, dass der Compiler die Definition der memory-Funktion manchmal nicht "findet":
template <DimType DIMENSION, class T> class QuadLeafManager { public: struct FileInterval { //... } } template <DimType DIMENSION, class T> size_t memory(const typename QuadLeafManager<DIMENSION, T>::FileInterval& fint) { return sizeof(fint); }In der Überladung von memory(QuadLeafManager) wird memory(std::vector<FileInterval>) aufgerufen:
error: no matching function for call to 'memory(const External::QuadLeafManager<4u, float>::FileInterval&)' sum += memory(u); // <- dies ist der Aufruf in memory(std::vector<T>)Die Variante für triviale Typen kann im Allgemeinen nicht per ADL gefunden werden. In einem Aufruf der Form
sum += memory(u);muss folglich das normale unqualifizierte Lookup erfolgreich sein. Befinden wir uns aber im Namensraum External, und befindet sich in External eine weitere Deklaration einer memory-Funktion, verdeckt diese nat. das Template im globalen Namensraum.
Die übliche Verfahrensweise ist hier, die Deklarationen, die nicht per ADL gefunden werden, per using-Deklaration in der Funktion bekannt zu machen.
Alsotemplate <class U> size_t memory(const std::deque<U>& obj) { using ::memory; // size_t sum = sizeof(obj); for (const U& u: obj) { sum += memory(u); } return sum; }Das ist die gleiche Herangehensweise die auch bei der Verwendung von swap genutzt werden sollte.
-
Hm, irgendwie bin ich gerade verwirrt. Wenn ich versuche, den Fehler durch ein Minimalbeispiel zu reproduzieren, kompiliert alles fehlerfrei.
Mit dem "using ::memory" hilft schon mal nicht.
Noch eine andere Frage:
Was kann ich machen, wenn ich möchte, dass memory(T& t) standardmäßig sizeof(t) zurückgibt?Edit:
ok, jetzt geht alles, auch wenn ich noch nicht genau vestehe warum.