Topic: options to varargs (LONG) Was: Methods with variable number arguments


Author: bill@osisoft.com (Bill Vaughan)
Date: 1996/12/26
Raw View
fknauss@qualcomm.com (Friedrich Knauss) wrote:

>
>The second variation involves named parameters, which applies more to
>how sunview functions used to work. They would look something like
>this (names are completely made up, but the idea is right)

<snippage>

>nice C++ way of doing this is to have a class which has as a friend
>the function being called, and has named functions for setting those
>values. For the example above it would look something like this:
>
>/////////////////////////////////////////////////////////
>
>class Window
>{
>public:
>   class Defaults; // forward decl
>   Window();
>   Window(Defaults &);
>   // all your other stuff
>};
>
>class Window::Defaults
>{
>   friend Window::Window(); // let default ctor have access as well
>   friend Window::Window(Window::Defaults &);
>   // this is where all the possible default data goes
>   int height;
>   int width;
>   Color foreground;
>   Color background;
>   // [...]more stuff
>public:
>   // ctor initializes to default values
>   Defaults():
>      height(24),
>      width(80),
>      foreground(Color::Black()),
>      background(Color::White()),
>      // ... more stuff
>   {}
>   // these functions change the values by name.
>   Height(int x)          {height = x;}
>   Width(int x)           {width = x;}
>   Foreground(Color c)    {foreground = c;}
>   Background(Color c)    {background = c;}
>   // more functions
>};
>/////////////////////////////////////////////////////////
>
>and is used as follows:
>
>Window wl;
>Window w2(Window::Defaults()
>         .Height(100)
>         .Width(100)
>         .Foreground(Color::Red())
>         .Background(Color::Blue())
>         .CursorType(Cursor::Crosshair())
>         );

Hmmm, I can't make this work even if I add a Color class and redeclare
the Window::Default setting routines to return Default& (which is
necessary to get the dot-operator to behave correctly). Problem is
that in the call to the w2 constructor, Window::Defaults() does NOT
specify the default constructor for the Defaults class; rather it
looks for a nonexistent function taking void. At least this is so in
Visual C++.

The best I could do was:

 Window::Defaults d;
 Window w2(d.Height(100).Width(100)
 // etcetera
 );

which compiles just fine but is lots uglier.  :)  Am I missing
something?
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: fknauss@qualcomm.com (Friedrich Knauss)
Date: 1996/12/20
Raw View
In article <32B9444F.398F@dit.ou.dk>,
Morten M. Christensen <mmc@dit.ou.dk> wrote:
>Hi,
>
>Is it legal in standard C++ to have methods with a variable
>number of arguments like printf ? I.e. Are the methods below
>legal ?

It is possible if you use <varargs.h>, but you end up throwing all
type safety and parameter counting verifications out the window. For
instance:

printf("%s\n", 1.2);
printf("%d %d\n", 3);

will both probably cause something spectacular to happen when you try
to execute them. There are a number of variations which get around
these problems. Both of these are stolen from other peoples posts,
authors long since forgotten, which is to bad since thses are really
good ideas. I put the one that may be more applicable first, but I
think they're both worth understanding.

                    - - -

The first variation, which was actually done to simulate printf, but
can work with other stuff, overloaded the comma operator to get the
multiple params. It looked something like this:

/////////////////////////////////////////////////////////

class format
{
public:
   friend ostream &operator <<(ostream&, format&);
   typedef bad_param;
   typedef too_many_params;
   typedef not_enuf_params;
   format(string);  // constructor takes the format string;
   format & operator,(double)() throw (bad_param, too_many_params);
   format & operator,(int)() throw (bad_param, too_many_params);
   // [...] more numerical types
   format & operator,(char)() throw (bad_param, too_many_params);
   format & operator,(char *)() throw (bad_param, too_many_params);

}

ostream &operator << (ostream &, format &) throw (format::not_enuf_params);

/////////////////////////////////////////////////////////

It is used like this:

cout << (format("%s %d\n"),"number:",3) << flush;

The two cases given above would look like

cout << (format("%s\n"), 1.2) << flush;   // throws bad_param
cout << (format("%d %d\n"), 3) << flush;  // throws not_enuf_params

Which would result in much less spectacular failures than the printf
versions.

                    - - -

The second variation involves named parameters, which applies more to
how sunview functions used to work. They would look something like
this (names are completely made up, but the idea is right)

/**//**//**//**//**//**//**//**//**//**//**//**//**//**/

WindowHandle w1 = WindowCreate(0); /* does default window */
WindowHandle w2 = WindowCreate( WIN_HEIGHT, 100,
    WIN_WIDTH, 100,
    WIN_FORGROUND, WIN_RED,
    WIN_BACKGROUND, WIN_BLUE,
    WIN_CURSOR, WIN_CROSSHAIR,
    WIN_TITLE, "My Special Window",
    0);

/**//**//**//**//**//**//**//**//**//**//**//**//**//**/

Basically, the parameters would come in pairs, with the first of the
pair being the name to which the second value would be applied. The
last parameter would have to be an invalid name, usually 0. A
nice C++ way of doing this is to have a class which has as a friend
the function being called, and has named functions for setting those
values. For the example above it would look something like this:

/////////////////////////////////////////////////////////

class Window
{
public:
   class Defaults; // forward decl
   Window();
   Window(Defaults &);
   // all your other stuff
};

class Window::Defaults
{
   friend Window::Window(); // let default ctor have access as well
   friend Window::Window(Window::Defaults &);
   // this is where all the possible default data goes
   int height;
   int width;
   Color foreground;
   Color background;
   // [...]more stuff
public:
   // ctor initializes to default values
   Defaults():
      height(24),
      width(80),
      foreground(Color::Black()),
      background(Color::White()),
      // ... more stuff
   {}
   // these functions change the values by name.
   Height(int x)          {height = x;}
   Width(int x)           {width = x;}
   Foreground(Color c)    {foreground = c;}
   Background(Color c)    {background = c;}
   // more functions
};
/////////////////////////////////////////////////////////

and is used as follows:

Window wl;
Window w2(Window::Defaults()
         .Height(100)
         .Width(100)
         .Foreground(Color::Red())
         .Background(Color::Blue())
         .CursorType(Cursor::Crosshair())
         );
--
-- fritzz@qualcomm.com
-- Pain is temporary, glory is forever.
--


[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]