Template-Überladung für Arraylänge
-
template <size_t N> size_t arrlen(const char (&arr)[N]) { std::cout << "array: "; return N; } size_t arrlen(const char *arr) { std::cout << "pointer: "; return 1+strlen(arr); } int main() { const char buf[] = "abc"; std::cout << arrlen(buf) << '\n'; }Ausgabe: "pointer: 4".
Krieg ich irgendwie hin, dass die erste Funktion aufgerufen wird? Es ist auch gewollt, dass das Verhalten unterschiedlich ist, wenn das Array Nullen enthält.
-
Einfache Variante:
template< class = int > size_t arrlen(const char *arr ) { std::cout << "pointer: "; return 1+std::strlen(arr); }Da auch die pointer Version ein template ist wird sie bei Überladung nicht mehr bevorzugt. Alternativ kann man die pointer Version auch anders zu einem schlechteren match machen als die mit array:
struct conv_incl { conv_incl( const char *arr_ ) { arr = arr_; } const char *arr; }; size_t arrlen( conv_incl c ) { std::cout << "pointer: "; return 1+std::strlen( c.arr ); }Vermutlich kann man das auch mit enable_if und type_traits machen, aber das ist umständlicher denk ich.
-
Fällt dir nichts auf?

Schreib malarrlen<4>(buf);
-
Dieser Name-Lookup in C++ ist wirklich verzwickt.
Aber danke dir, GorbGorb, du hast mir sehr geholfen!
-
Hacker schrieb:
Fällt dir nichts auf?

Doch, das ist mir schon aufgefallen (es beweist, dass die Funktion prinzipiell stimmt). Nützt mir nur nichts, weil wenn ich die Länge schon hätte, bräuchte ich dafür doch keine Funktion

-
adler schrieb:
Hacker schrieb:
Fällt dir nichts auf?

Doch, das ist mir schon aufgefallen (es beweist, dass die Funktion prinzipiell stimmt). Nützt mir nur nichts, weil wenn ich die Länge schon hätte, bräuchte ich dafür doch keine Funktion

Dann mach doch nicht so eine Funktion? Wofür brauchst du das überhaupt? Merke: Hier im Forum hilft man bei deinem Haupt-Problem, nicht bei den Problemen die entstanden als deine C++-Einschränkungen ins Spiel kamen.
-
Hacker schrieb:
Merke: Hier im Forum hilft man bei deinem Haupt-Problem, nicht bei den Problemen die entstanden als deine C++-Einschränkungen ins Spiel kamen.
Ihm wurde schon längst geholfen. Mit deinem Beispiel zeigst du eigentlich nur, dass du die Funktion nicht verstanden hast. Sie taucht öfter hier im Forum auf. Such einfach mal danach.
-
Ja Hacker glänzt heute wieder besonders.
@Topic: Array-Länge ist eine Sache, wo ich immer noch nen Makro verwende. Das funktioniert nämlich auch mit älteren Compilern, und mit allen möglichen und unmöglichen Typen (internal linkage etc.).
-
Mal aus Interesse: In welchem Zusammenhang braucht man "eine" Funktion, die sich einmal wie strlen() + 1, und einmal wie sizeof(a)/sizeof(*a) verhält? Das sind in meinen Augen zwei _völlig_ unterschiedliche Dinge - die ich nicht nur aus Designgründen nicht mischen würde, sondern für die mir auch kein gemeinsamer Anwendungsfall einfällt.
-
Also deine template built-ins machen nur Sinn, wenn es einen Grund gäbe, dass das N vor der Laufzeit (also zur Compilezeit) bekannt sein sollte. Gründe dafür hat deine Funktion eigentlich keine. Ja aus einem Pointer kann man nicht mehr rauslesen wie viele Elemente darin enthalten sind, aber dafür kannst du z.B. vector oder einfach einen string benutzen und schon liefert das Objekt die zusätzlichen Funktionen. Ansonsten musst du halt die Länge als separate Parameter übergeben wie es die komplette CRT macht! memset(..,..., Länge), memcpy(..,.., Länge).
Wenn du mit zero-terminierten chars arbeitest(wie in deinem Beispiel) funktioniert strlen(chars) natürlich genauso und du brauchst keine zusätzlichen Parameter.Aber diese built-ins sollten eher für zur Entwicklungszeit unbekannte, aber dann zur Compilezeit bekannten Datenlängen vom Stack benutzt werden. z.B.
template<int R, int C>class Matrix;oder für zeitkritischen inline Code z.B.
template<unsigned int>struct Fakulitaet;
-
Hier noch eine exotische Variante (ich würde aber nicht darauf vertrauen, dass das jeder Compiler richtig hinbekommt):
size_t arrlen(const volatile char *arr) { std::cout << "pointer: "; return 1+strlen(const_cast<const char*>(arr)); }(Sollte nat. nicht mit volatile-Objekten verwendet werden).
-
Mir ist klar, dass 'N' erst zur Laufzeit berechnet wird und man es bei solchen Konstrukten nicht anzugeben braucht.
Edit: Zu meinem Beispiel: war als Scherz gemeint
, ich meinte er kann die Länge als Template-Parameter explizit angeben und dadurch den Aufruf der entsprechenden Funktion erzwingen. Kam schlecht an, fürchte ich. Die Fragestellung war mir zu ungenau.
-
Hacker schrieb:
Zu meinem Beispiel: war als Scherz gemeint

rofl, ich lach mich schlapp

-
Hacker schrieb:
Mir ist klar, dass 'N' erst zur Laufzeit berechnet wird.
Überleg besser nochmal, wie das mit den Templates zur Laufzeit war.
-
Michael E. schrieb:
Hacker schrieb:
Mir ist klar, dass 'N' erst zur Laufzeit berechnet wird.
Überleg besser nochmal, wie das mit den Templates zur Laufzeit war.
Dann Compile-Zeit (meinte ich ja). Es heißt ja so schön "Template-meta programmierung".