Parameterkette in Funktionssignatur (...)
-
Hi,
man sieht ab und an mal in Funktionen mit der Definition in der Art void foo(int i, ...); - zum Beispiel bei einigen printf Derivaten. Damit werden irgendwie die Parameter verlängert. Wie funktioniert dies und sollte man das auch selber (wo es Sinn macht) verwenden oder hat das Nachteile?
danke
-
-
Ist nicht zu empfehlen solange man es nicht unbedingt braucht, da nicht typsicher etc.
Nennen tut man das "varargs".
-
Es ist nicht nur nicht typsicher, wenn es mit C++-Objekten gefüttert wird erzeugt es auch noch undefiniertes Verhalten.
Es gibt aber einen sehr vielversprechenden Ansatz für eine Spracherweiterung deren Namen mir gerade nicht einfällt, die das ganze dann "ordentlich" über Templates erledigen kann.
-
Erwähnenswert ist noch, dass die Ellipse manchmal beim Überladen ganz praktisch ist, weil sie am schlechtesten auf einen Parametertyp passt.
-
Geht mal in google nach "variadic templates" suchen!!
-
.filmor schrieb:
Es ist nicht nur nicht typsicher, wenn es mit C++-Objekten gefüttert wird erzeugt es auch noch undefiniertes Verhalten.
Es gibt aber einen sehr vielversprechenden Ansatz für eine Spracherweiterung deren Namen mir gerade nicht einfällt, die das ganze dann "ordentlich" über Templates erledigen kann.variadic templates schimpft sich des sichere
-
ich benutz das aber erst wenn das offiziell ist. Sieht aber schonmal cool aus.
-
r0nny schrieb:
variadic templates schimpft sich des sichere
lemonhead schrieb:
ich benutz das aber erst wenn das offiziell ist. Sieht aber schonmal cool aus.
EDIT: sieht wie ich finde grässlich aus, aber jedem das Seine

Bis dahin könnte man doch ein einfaches Template verwenden, und die varargs als z.B. boost::tuple übergeben. Ist zwar nicht gut dokumentiert, aber Boost.Tuple hat ein "head" und ein "tail" member, wobei "head" das erste Element ist, und "tail" das letzte (bzw. eine "get_head" und eine "get_tail" Funktion). Und mit einer spezialisierung auf "boost::tuple<>" kann man die rekursive template instanzierung abbrechen.
Sollte relativ einfach machbar sein... und funktioniert mit dem heutigen C++ Standard und heute verfügbaren Compilern.
-
Das macht aber nicht das, wofür man es braucht (nämlich variable Anzahl von Parametern).
Btw., tail ist nicht das letzte Element sondern der Rest des Tupels.
-
Benutz den Preprocessor um dir automatisch überladene Funktionen für bis zu einer geweissen Anzahl Parameter zu generiren. Ist das beste was du mit dem jetztigen Standard hinkriegst.
Beispiel:
#include <boost/preprocessor.hpp> #include <iostream> #define OP_SHIFT(z, n, arg)\ << arg ## n #define MY_PRINT(z, n, data)\ template<BOOST_PP_ENUM_PARAMS(n ,class T)>\ void my_print(BOOST_PP_ENUM_BINARY_PARAMS(n, const T, &t))\ {\ std::cout BOOST_PP_REPEAT_ ## z(n, OP_SHIFT, t) <<std::endl;\ } BOOST_PP_REPEAT_FROM_TO(1, 10, MY_PRINT, nil) #undef OP_SHIFT #undef MY_PRINT int main(){ my_print(1, " + ", 3, '=', 1+3); }
-
@.filmor:
ja, sorry, natürlich ist tail der Rest, alles bis aufs erste Element halt.
Und natürlich ist es ein syntaktischer Unterschied, aber ich kann immernoch schreibenfoo("%s %s %s", boost::make_tuple("sepp", "hugo", "franz")); foo("%s", boost::make_tuple("dings")); foo("zonk", boost::tuple<>());Wenn die genaue Syntax zum Aufruf nicht vorgegeben ist, ist das ein möglicher ersatz. Wenn man natürlich darauf besteht dass foo selbst (und nicht make_tuple) eine variable Anzahl an Parametern frisst ist es kein Ersatz.
-
Du könntest es folgendermasen machen:
template<class Tuple> void foo_impl(const Tuple&){ } MAKE_VAR_FUNC(foo)MAKE_VAR_FUNC würde die nötigen Überladungen erzeugen und alle Parameter als Tuple an foo_impl weiterleiten. Man könnte auch noch ein zusätzlicher Makroparameter einbauen um normale Parameter zu erlauben.
Da MAKE_VAR_FUNC O(n) ist wo n die maximale Anzahl der Parameter ist wäre könnte man diesen Wert locker auf irgend einen hohen Wert setzen.
Würde doch in etwa das rauskommen was da versucht wurde als Sprachelement nachzubauen, oder?