Problem mit partieller Spezialisierung
-
Servus,
ich möchte eine Memberfuktion ihre Überladung aufrufen lassen, wenn die Klasse mit einer Länge > 0 instantiiert wurde. Etwa so:
template <typename T, size_t length = 0> class Foo { void bar(); void bar(size_t n); }; template <size_t length> void Foo<std::vector<char>, length>::bar() { bar(length); }gcc quittiert mir das mit einem
error: invalid use of undefined type `class Foo<std::vector<char, std::allocator<char> >, length>' error: template definition of non-template `void Foo<std::vector<char, std::allocator<char> >, length>::bar()' In member function `void Foo<std::vector<char, std::allocator<char> >, length>::bar()': error: there are no arguments to `bar' that depend on a template parameter, so a declaration of `bar' must be available error: (if you use `-fpermissive', G++ will accept your code, but allowing the use of an undeclared name is deprecated)Ich müsste jetzt in die Bibliothek laufen und mir den Alexandrescu holen, denn ich erinnere mich schwach, dass es da ein Konstrukt gibtt, was genau diesen Mechanismus erlaubt.
Weiß das jemand aus dem Kopf?
Philipp
-
Du mußt die Spezialisierung (glaub ich) vorher deklarieren:
template <typename T, size_t length = 0> class Foo { public: void bar(); void bar(int n); }; template <size_t length> class Foo<std::vector<char>, length> { public: void bar(); }; template <size_t length> void Foo<std::vector<char>, length>::bar() { bar(length);}Gruß,
CSpille
-
Bißchen unpraktisch, wenn die Klasse vier Konstruktoren und noch vier andere Memberfunktionen enthält - muss ich die dann alle kopieren ?? Das ging iwie einfacher.
-
Dreh den Spieß doch um und spezialisier die 0-Methode:
#include <iostream> #include <vector> template <typename T, size_t length> class Foo { public: void bar() { this->bar(length); } void bar(size_t n){ std::cout << "Nicht null, sondern " << length << "..." << std::endl; } }; template <> void Foo<std::vector<char>, 0>::bar() { std::cout << "Null..." << std::endl; } int main() { Foo<std::vector<char>, 0> f; Foo<std::vector<char>, 1> f1; f.bar(); // "Null..." f1.bar(); // "Nicht null, sondern 1..." return 0; }
-
Falls du ne schöne Lösung findest (keinen Workaround), dann bitte das
posten nicht vergessen
-
Template-Metaprogrammierung:
struct FooImplImpl { void bar(size_t n); }; template <size_t length> struct FooImpl : FooImplImpl { using FooImplImpl::bar; void bar() { bar(length); } }; template <> struct FooImpl<0> : FooImplImpl { using FooImplImpl::bar; void bar() { bla(); } }; template <typename T, size_t length = 0> struct Foo : FooImpl<length> { };Aber weil die C++ler immer zu kompliziert denken:
template <typename T, size_t length = 0> struct Foo { void bar() { if (length > 0) bar(length); else bla(); } void bar(size_t n); };