Teilspezialisierung von Funktions-Templates
-
Abend.
//Funktions-Template template< int N, class T > void test() { } //Spezialisierung 1 template< > void test< 3, float>() { }Soweit funktioniert das ja ganz gut. Bekomme ich jetzt auch irgendwie eine Teilspezialisierung t< 3, T[variabel] > hin?
-
krabbels schrieb:
Abend.
//Funktions-Template template< int N, class T > void test() { } //Spezialisierung 1 template< > void test< 3, float>() { }Soweit funktioniert das ja ganz gut. Bekomme ich jetzt auch irgendwie eine Teilspezialisierung t< 3, T[variabel] > hin?
nein. Partielle Spezialisierung ist nur mit Klassentemplates möglich. Du könntest also das Funktionstemplate dazu nutzen, einen Funktor aufzurufen, und diesen dann entsprechend partiell spezialisieren.
-
Auch sehr häufig sieht man die Methode aus "Modernes C++ Design" (k.A. wo es erfunden wurde):
template <typename T> struct type2type { typedef T type; }; template <typename T> void do_something (T const& p) { do_something (type2type<T> (), p); } void do_something (type2type<double>, double param); void do_something (type2type<int>, int param);Ist letztlich aber dasselbe.
-
.filmor schrieb:
Auch sehr häufig sieht man die Methode aus "Modernes C++ Design" (k.A. wo es erfunden wurde):...
Sorry, magst Du das kurz erläutern ?
Ich verstehe nicht, was es mit der 2Parameter-version von do_something() auf sich hat ....Gruß,
Simon2.
-
Könnte man nicht auch einfach eine statische Methode einer Klasse benutzen (die man ja partiell spezialisieren kann)?
//Funktions-Template template<int N, class T> class Wrapper { public: static void test() { } }; //Spezialisierung template<class T> class Wrapper<3, T> { static void test() { } }Das hätte halt den Nachteil, dass bei Klassen die Template-Argumente nicht aus irgendwelchen Argumenten bestimmt werden können...
Die Methode von .filmor verstehe ich aber auch nicht...
Felix
-
Simon2 schrieb:
Ich verstehe nicht, was es mit der 2Parameter-version von do_something() auf sich hat ....
Das ist in etwa die Methode, die man auch bei Iterator"spezialisierungen" nutzt: Eine (hypothetische) Funktion advance mit zwei Parametern ruft eine zweite Funktion advance_impl auf, und übergibt ihr als dritten Funktionsparameter eine Instanz des Iteratoren-Tag. Nun überlädt man advance_impl für das allgemeinste Iterator-Tag, sowie für jedes Tag, für das man Optimierungen anbieten kann. Da beim Lookup einer Funktion die Überladung mit den am besten passenden Parametern genommen wird, wird diese dann aufgerufen.
template< typename It > void advance( It& it, size_t off ) { advance_impl( it, off, typename It::iterator_category() ); } template< typename It > void advace_impl( It& it, size_t off, std::forward_iterator_tag ) { while (off--) ++it; } template< typename It > void advance_impl( It& it, size_t off, std::random_access_iterator_tag ) { it += off; }Ergänzung: Der Typ des Zusatzparameters muss natürlich nicht in einer Vererbungshierarchie stecken, das sichert hier zusätzlich nur ab, dass z.B. bidirectional Iteratoren auf die Forward-Funktion zurückfällt.
-
Phoemuex schrieb:
...
Das hätte halt den Nachteil, dass bei Klassen die Template-Argumente nicht aus irgendwelchen Argumenten bestimmt werden können...... aber das geht bei argumentlosen Funktionstemplates sowieso nicht.

Aber das bringt mich auf eine andere Idee: Wie wär's mit einen template-Member ?
template <int N> struct Wrapper { template <typename FType> static void f(FType); }; template <> struct Wrapper<3> { template <typename FType> static void f(FType) { // hier "3-spezifisches" und FType-generelles } };Damit kann man wenigstens einen Typen (FType) beim Aufruf automatisch bestimmen lassen...
LordJaxom schrieb:
...
Ahaaa !!

Danke, das hatte mir noch gefehlt!

Gruß,
Simon2.