Topic: Named arguments function calls; was C++0x


Author: "Paul Mensonides" <pmenso57@home.com>
Date: Wed, 23 May 2001 09:00:20 GMT
Raw View
"Mirek Fidler" <cxl@volny.cz> wrote in message news:9ebnta$1rph$1@news.vol.cz...

[clip]

|     Well, but perhaps you did not get the whole point. There is no
| WindowData to pass parameters to CreateWindow. You pass them to Window
| object itself (at least you would, using our GUI library ;-). You can use
| them to change windows attributes after windows is created too. So you get
| here more functionality WITHOUT introducing named arguments.
|
| Mirek

Don't worry, the last was more of a joke (an obviously asinine way to have
named-like arguments).  That is not my point, however, I'm saying that both
approaches are viable in certain (common) situations.  Given what I said before:
asynchronous calls.  What is the point of passing an entire struct by *value*
rather than passing the parameters separately (i.e. avoiding free store).  All
that you do in such a case is add memory to hold struct padding.  Plus, you have
to do this:

MyStruct x = { 10, 10, 10, 10, ..whatever.. };
AsyncCall(x);

Instead of this:

AsyncCall(10, 10, 10, 10, ..etc.. );

There are valid situations for both approaches, that is all I'm saying.  Also,
that keyword arguments (named arguments) would not affect your example at all.
It would just make some *other* things easier, more understandable, and decrease
"source code" bloat.

Paul Mensonides

---
[ 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    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: "Mirek Fidler" <cxl@volny.cz>
Date: Mon, 21 May 2001 18:52:27 GMT
Raw View
> // Window a;
> //
> // a.Width(0).Height(1).OtherArg(3).OtherArg2(4).Transparency(200);
> //
> // Mirek
>
> How about:
>
> inline Window* CreateWindow(int height = 100, int width = 100, BorderStyle
> border = NO_BORDER, int otherArg1 = 0, int otherArg2 = 0, unsigned char
trans =
> 255);
>
> This is *can be* more efficient (memory-wise) than creating a struct (with
> padding) and passing a reference. In that case, you have the padding plus
the
> size of the pointer (for the reference). You raise an interesting point,
> however. Apparently, you CAN use keyword arguments (sort of):
>
> struct WindowData {
>   int width, height, otherArg1, otherArg2;
>   BorderStyle border;
>   unsigned char trans;
>   inline WindowData(void) : height(100), width(100), border(NO_BORDER),
> otherArg1(0), otherArg2(0), trans(255) {
>     return;
>   }
>   inline WindowData& Width(int a) {
>     width = a;
>     return *this;
>   }
>   inline WindowData& Height(int a) {
>     height = a;
>     return *this;
>   }
>   inline WindowData& Border(BorderStyle a) {
>     border = a;
>     return *this;
>   }
>   inline WindowData& OtherArg1(int a) {
>     otherArg1 = a;
>     return *this;
>   }
>   inline WindowData& OtherArg2(int a) {
>     otherArg2 = a;
>     return *this;
>   }
>   inline WindowData& Trans(unsigned char a) {
>     trans = a;
>     return *this;
>   }
> };
>
> inline Window* CreateWindow(int Height = 100, int Width = 100, BorderStyle
> Border = NO_BORDER, int OtherArg1 = 0, int OtherArg2 = 0, unsigned char
Trans =
> 255);
>
> inline Window* CreateWindow(const WindowData& w) {
>   return CreateWindow(w.height, w.width, w.border, w.otherArg1,
w.otherArg2,
> w.trans);
> }

    Well, but perhaps you did not get the whole point. There is no
WindowData to pass parameters to CreateWindow. You pass them to Window
object itself (at least you would, using our GUI library ;-). You can use
them to change windows attributes after windows is created too. So you get
here more functionality WITHOUT introducing named arguments.

Mirek




---
[ 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    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: "Paul Mensonides" <pmenso57@home.com>
Date: Sat, 19 May 2001 09:03:41 GMT
Raw View
Mirek Fidler wrote:

// BTW, in this concrete example (wa are creating GUI libraries too ;-)
// there is another viable option:
//
// Window a;
//
// a.Width(0).Height(1).OtherArg(3).OtherArg2(4).Transparency(200);
//
// Mirek

How about:

inline Window* CreateWindow(int height = 100, int width = 100, BorderStyle
border = NO_BORDER, int otherArg1 = 0, int otherArg2 = 0, unsigned char trans =
255);

This is *can be* more efficient (memory-wise) than creating a struct (with
padding) and passing a reference. In that case, you have the padding plus the
size of the pointer (for the reference). You raise an interesting point,
however. Apparently, you CAN use keyword arguments (sort of):

struct WindowData {
  int width, height, otherArg1, otherArg2;
  BorderStyle border;
  unsigned char trans;
  inline WindowData(void) : height(100), width(100), border(NO_BORDER),
otherArg1(0), otherArg2(0), trans(255) {
    return;
  }
  inline WindowData& Width(int a) {
    width = a;
    return *this;
  }
  inline WindowData& Height(int a) {
    height = a;
    return *this;
  }
  inline WindowData& Border(BorderStyle a) {
    border = a;
    return *this;
  }
  inline WindowData& OtherArg1(int a) {
    otherArg1 = a;
    return *this;
  }
  inline WindowData& OtherArg2(int a) {
    otherArg2 = a;
    return *this;
  }
  inline WindowData& Trans(unsigned char a) {
    trans = a;
    return *this;
  }
};

inline Window* CreateWindow(int Height = 100, int Width = 100, BorderStyle
Border = NO_BORDER, int OtherArg1 = 0, int OtherArg2 = 0, unsigned char Trans =
255);

inline Window* CreateWindow(const WindowData& w) {
  return CreateWindow(w.height, w.width, w.border, w.otherArg1, w.otherArg2,
w.trans);
}

// now you *can* use "named" arguments, with default arguments, specified in any
order...

void f() {
  WindowData _; // note: underscore identifier
  Window* w =
CreateWindow(_.Height(500).Border(SMALL_BORDER).OtherArg2(1).Trans(100));
  return;
}

Paul Mensonides

---
[ 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    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: "Paul Mensonides" <pmenso57@home.com>
Date: Thu, 17 May 2001 11:30:53 GMT
Raw View
"Andrew R. Thomas-Cramer" <artc@prism-cs.com> wrote in message
news:3b02e766$0$42869$272ea4a1@news.execpc.com...
:
: This was considered in the past and withdrawn. See "Keyword Arguments" in
: D&E for the reasoning.

The reasoning is not that great however.  It was mostly that they considered it
a frill rather than a necessity.  All of the other arguments could be handled
easily.

It need not apply across translation units any more than default arguments do.
You must have a function prototype anyway.  Ambiguities could be handled easily
by the compiler.  Changing the names in a library header could be easily made
backward compatible. i.e....

class X {
    public:
        void f(int A, int B); // new version
};

void X::f(int x, int y); // old version

void X::f(int A, int B) {
    // definition
}

If you didn't have named arguments, you simply couldn't specify the arguments by
name:

void f(int, int);

void g() {
    f(? = 10, ? = 10); // ?
}

Likewise calls could be made ambiguous by asinine usage:

void f(int x, int y);
void f(int y, int x); // reversed argument names

void g() {
    f(x := 2, y := 1); // ambiguous
}

However this wouldn't be ambiguous:

void f(int x, int y);
void f(int Param1, int Param2);

void g() {
    f(Param2 := 1, x := 2);
}

You could also get rid of the "default arguments must be trailing arguments"
rule:

void f(int x = 10, int y = 10, int z);

void g() {
    f(,,5); // *blank* parameters (other languages can do this)
}

You could also legalize *identical* parameter arguments per translation unit:

void f(int x = 0);
void f(int Param2 = 0); // legal (defaults identical)

void f(int x = 0);
void f(int x = 2); // illegal

Granted, this is all just syntactic convenience, but it would not make the
language more complicated than it already is, and it would make some things
*more* clear (a typical example):

Window* CreateWindow(BorderEnum BorderType = NONE, int Width = 100, int Height =
100 /*etc. etc....*/ );

void someFunc() {
    g_wnd = CreateWindow( , , 100);
    // or...
    g_wnd = CreateWindow(Height := 200);
}

This can be significantly more readable and less annoying to type.  Discouraging
use a functions with long parameter lists is undermining the multi-paradigm
abilities of C++.  Likewise, a function that can be used by some other language
tends to not work well as a class member anyway (whereas almost everything
understands 'extern "C"').  I'm not saying that this is the best way to do
something like this within C++, however, I am saying you should be able to do it
anyway that you like (personal preferences, etc.), and C++ should support this.
I.e. C++ should directly fully support all the paradigms it claims to support.
C++ programmers shouldn't, and don't, need coddling by the standards committee.
If I want to do something like make a switch-on-type function (whether it's is
bad style or not (and it isn't always bad style)), C++ should support the
paradigm and not discourage it.  What C++ *should* encourage is the use of
multiple paradigms.  Currently, C++ tends to strongly favor classes and
templates, rather than straight-forward procedural programming.  I'm not
knocking classes and templates (most of what I do uses them).  I'm just
'un-knocking' regular procedural programming.

Paul Mensonides

---
[ 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    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: =?iso-8859-1?Q?Andr=E9_P=F6nitz?= <poenitz@htwm.de>
Date: Thu, 17 May 2001 17:39:10 GMT
Raw View
Paul Mensonides <pmenso57@home.com> wrote:
> Window* CreateWindow(BorderEnum BorderType =3D NONE, int Width =3D 100,=
 int Height =3D
> 100 /*etc. etc....*/ );
>=20
> void someFunc() {
>     g_wnd =3D CreateWindow( , , 100);
>     // or...
>     g_wnd =3D CreateWindow(Height :=3D 200);
> }

What's wrong with

struct WindowData {
 WindowData() : BorderType(NONE) ... {}
  BorderEnum BorderType ...
};

Window* CreateWindow(WindowData const &);

void someFunc() {
   WindowData w;
   w.Height =3D 100
   g_wnd =3D CreateWindow(w);
   ...

> This can be significantly more readable and less annoying to type.
> Discouraging use a functions with long parameter lists is undermining t=
he
> multi-paradigm abilities of C++.

I'd rather think discouraging funcions with long parameter lists is a
good idea.

What do you do if you need to factor out some part of such a function?
  Pass around each of its arguments? Inefficient and unreadable...

What if you need an additional parameter?
  Change all of your functions including those that simply delegate work?

Andre'

--=20
Andr=E9 P=F6nitz ............................................. poenitz@ht=
wm.de

---
[ 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    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: "Paul Mensonides" <pmenso57@home.com>
Date: Fri, 18 May 2001 03:02:56 GMT
Raw View
"Andr    P   nitz" <poenitz@htwm.de> wrote in message
news:9e1166$123$1@narses.hrz.tu-chemnitz.de...
Paul Mensonides <pmenso57@home.com> wrote:
> Window* CreateWindow(BorderEnum BorderType = NONE, int Width = 100, int Height
=
> 100 /*etc. etc....*/ );
>
> void someFunc() {
>     g_wnd = CreateWindow( , , 100);
>     // or...
>     g_wnd = CreateWindow(Height := 200);
> }

/ What's wrong with
/
/ struct WindowData {
/ WindowData() : BorderType(NONE) ... {}
/   BorderEnum BorderType ...
/ };
/
/ Window* CreateWindow(WindowData const &);
/
/ void someFunc() {
/    WindowData w;
/    w.Height = 100
/    g_wnd = CreateWindow(w);
/    ...

There is nothing wrong with using a class instead, it is just not always a
feasible option (i.e. integrating with other languages).  I'm not saying this
isn't an ideal way to do something within C/C++.  I'm saying this isn't the
*only* valid way to handle this.

> This can be significantly more readable and less annoying to type.
> Discouraging use a functions with long parameter lists is undermining the
> multi-paradigm abilities of C++.

/ I'd rather think discouraging funcions with long parameter lists is a
/ good idea.
/
/ What do you do if you need to factor out some part of such a function?
/   Pass around each of its arguments? Inefficient and unreadable...

That depends:

What about an asynchronous call?  I can't safely pass a reference in such a
situation.  So maybe instead I pass the struct itself:

    void AsyncCreateWindowThatHandlesItself(WindowData);

(Or if you want to avoid the possible overhead of RTTI, possible
exception-handling complexities, etc..)
(also consider generic programming to handle multiple parametized argument
functions, say a 'for_each' type of thing)

But this can be more inefficient because a struct is a contiguous block of
memory that may include extra alignment padding, therefore it couldn't
necessarily be stored in, say, another processor's registers (though it could
probably be stored in cache memory).  It depends on the architecture.  I'll
reiterate:  I am not saying that this is better (nor am I saying that it is
worse).  I'm saying that this is *a* paradigm, and a perfectly valid one, not
just some legacy way of doing things. --which brings up another point:  legacy
code.  What if I *already* have this function all over the place in code written
five years ago, and I want to slightly extend it?  Do I overhaul the whole
structure of an application instead of do this:

old version:
Window* CreateWindow(int h = 0, int w = 1, int border = 2, int otherArg = 3, int
otherArg2 = 4);

new version:
Window* CreateWindow(int h = 0, int w = 1, int border = 2, int otherArg = 3, int
otherArg2 = 4, int transparency = 0);

void f() {
    Window* a = CreateWindow(transparency := 200);
    // -or-
    Window* b = CreateWindow(,,,,,200); // granted, not as readable, but as
readable as:
        // CreateWindow(0, 1, 2, 3, 4, 200);
}

I could instead write a wrapper function that does the above for new code, but
that also adds another layer of complexity to the source code as well.  The
point is, there are pros and cons to both approaches, and an end-all-and-be-all
statement that is contrary to that is ridiculous.  This goes into the
fundamental ideal of C++:  a general-purpose programming language.  As another
similar type of situation, everyone seems to say, "use vector<> instead of
normal arrays."  But low-level coding *requires* that you use the 'low-level'
features of C++ which tends to be significantly more convoluted and harder to
debug.  So how would syntactic conveniences such as this one make things worse?
By supposedly encouraging this *style* of programming, despite the fact that
this style is sometimes necessary anyway?  After all, vector<> is not
implemented using vector<>, and what if I need my own vector type because a
certain class doesn't meet the requirements of std::vector<>'s implementation.
(i.e. what *can* be collected by an STL container).  Then I end up making my own
using low-level coding that is significantly more convoluted than it could be
with a few syntactic shortcuts.

/ What if you need an additional parameter?
/   Change all of your functions including those that simply delegate work?
/
/ Andre'

You're point is a valid one, and, given free reign to modify other's
implementation or write new code from scratch, it is the path that I would
likely take in most cases.  But what I *like* best, or what I say *is* best, is
arbitrary and irrelevant.  Who am I (or anyone else) to say which is absolutely
better, since more things are involved than just technical issues such as
efficiency and *supposed* good style.  Say that I am revolted by the whole
concept of aggregate types and only use them when absolutely necessary (take it
as a given that I run my own company :) ).  Whether or not I'm digging myself
into a hole is my own problem.  A *lot* of good software has been written
without aggregates.  This is a tried-and-true programming paradigm, therefore it
should be FULLY supported.  Likewise, OOP should be FULLY supported.  Likewise,
generic progamming should be FULLY supported.  Likewise, Rule-based (ala R++,
but with better syntax) programming should be FULLY supported, etc..  What
happens when all our great class hierarchies are no longer *popular* because of
some newer and *better* style of programming is invented?  All of the sudden,
classes get no new features or improvements.  Bottom line:  if it works, support
it directly, rather than force the programmer to hack around it by manually
which creates *bad code*.  Multi-methods, for instance:  given some functions
with two 'virtual' arguments, with only three possible classes types could be
implemented with a 3x3 table of function pointers and an int per vtbl of the
class.  Granted, this scales up rapidly without severe optimization, however it
is not a whole lot different than a full class hierarchy with a bunch of virtual
functions to fake it in *good* OOP style (maybe Visitor patterns or something)
or relying on the inefficiency of RTTI.  C++ may have failed at the beginning
with 'too many' features, but that is not going to happen anymore.  Of course,
new features must be added over time to prevent compiler vendors from ignoring
the standards committee and fragmenting the language.  But C++ is not going away
no matter what gets added to it, it's already too popular.

Paul Mensonides

--
Andr    P   nitz ............................................. poenitz@htwm.de

---
[ 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    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]

---
[ 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    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: "Andrew R. Thomas-Cramer" <artc@prism-cs.com>
Date: Wed, 16 May 2001 20:49:22 GMT
Raw View
This was considered in the past and withdrawn. See "Keyword Arguments" in
D&E for the reasoning.

"Radoslav Getov" <nospam@mai.com> wrote in message
news:tfiogqn2aq5r48@corp.supernews.com...
> How about named argument funciton calls? I know it would be too large a
> step, but anyway:
>
> In Ada (I think) it's possible to do this:
>
> void rotate (double x, double y, double rotation);
>
> rotate  (rotation = Pi, x = y = 0 ); // the same as rotate (0, 0, Pi)
> rotate  (0, 0, rotation = Pi); // still the same
>...


---
[ 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    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: Christopher Eltschka <celtschk@dollywood.itp.tuwien.ac.at>
Date: Fri, 11 May 2001 13:39:05 GMT
Raw View
Christopher Eltschka wrote:
>
> Radoslav Getov wrote:
> >
> > "Dennis Yelle" <dennis51@jps.net> wrote in message
> > news:3AEF1353.87673842@jps.net...
> > > So, what do we want?
> > >
> > [snip]
> >
> > How about named argument funciton calls? I know it would be too large a
> > step, but anyway:
> >
> > In Ada (I think) it's possible to do this:
> >
> > void rotate (double x, double y, double rotation);
> >
> > rotate  (rotation = Pi, x = y = 0 ); // the same as rotate (0, 0, Pi)
> > rotate  (0, 0, rotation = Pi); // still the same
> >
> > rotate  (1, 2, z = 5) // error here - 'z' - no such argument name
> > rotate  (1, 2, x = 5) // error here - 'x' already passed by position
> >
> > Justification:
> > - positional arguments calls tend to be buggy, especially if arguments are
> > of
> > same (or similar) types
> > - improving readability; e.g. 'func (check_it <= true)' is much more
> > clear (at the point of call) than just func (true);
> >
> > Surely for the purpose of compatibility the notation probably cannot be
> > exactly as shown above, but I hope there is a way to do it.
>
> I think an argument should be _either_ named _or_ positional.
> This would also allow overloading on argument names.
>
> Example:
>
> class Complex
> {
> public:
>   Complex(double x, double y = 0): re(x), im(y) {}
>   Complex(re: double = 0, im: double = 0): re(re), im(im) {}
>   Complex(abs: double = 1, arg: double):
>     re(abs * cos(arg)), im(abs* sin(arg)) {}
>   // ...
> private:
>   double re, im;
> };
>
> Complex a, // 0
>         b(1.5), // 1.5
>         c(2.2, 1.7), // 2.2 + 1.7i
>         d(abs:2, arg: 3), // 2*e^(3i)
>         e(arg: 1.7), // e^(1.7i)
>         f(re: 5), // 5
>         g(im: 2), // 2i
>         h(im: 7, re: 8); // 8+7i
>
> The ":" versions are named arguments.
>
> Of course, named and unnamed arguments may be used in the same
> signature. In calls, arguments without "foo:" are matched up with
> positional arguments, and arguments with "foo:" match the
> corresponding named arguments.
>
> One has to be careful not to create ambiguities (f.ex. in the
> Complex class, only the second constructor can be used as
> default constructor; if the first one had a default argument
> on the first positional argument, then the definition of a
> would be ambiguous.
>
> For operators, there's a possible ambiguity with labels:
>
> T operator+(foo: T, T);
>
> foo: T() + T();
> // Label or argument name?
>
> This should be resolved as label.
> To get the named argument, one would have to write
>
> (foo: T() + T());

One side remark:

Named arguments which are clearly separated from positional
arguments would also allow to solve the question how to name
"move constructors" and "move assignment":

class X
{
public:
  X(X const&); // copy constructor
  X(move: X&); // move constructor

  X& operator=(X const&); // copy assignment
  X& operator=(move: X&); // move assignment
};

Now, a swap could be written like this:

void swap(X& a, X& b)
{
  X tmp(move: a);
  a = move: b;
  b = move: tmp;
}

---
[ 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    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: Christopher Eltschka <celtschk@dollywood.itp.tuwien.ac.at>
Date: Wed, 9 May 2001 22:12:56 GMT
Raw View
Radoslav Getov wrote:
>
> "Dennis Yelle" <dennis51@jps.net> wrote in message
> news:3AEF1353.87673842@jps.net...
> > So, what do we want?
> >
> [snip]
>
> How about named argument funciton calls? I know it would be too large a
> step, but anyway:
>
> In Ada (I think) it's possible to do this:
>
> void rotate (double x, double y, double rotation);
>
> rotate  (rotation = Pi, x = y = 0 ); // the same as rotate (0, 0, Pi)
> rotate  (0, 0, rotation = Pi); // still the same
>
> rotate  (1, 2, z = 5) // error here - 'z' - no such argument name
> rotate  (1, 2, x = 5) // error here - 'x' already passed by position
>
> Justification:
> - positional arguments calls tend to be buggy, especially if arguments are
> of
> same (or similar) types
> - improving readability; e.g. 'func (check_it <= true)' is much more
> clear (at the point of call) than just func (true);
>
> Surely for the purpose of compatibility the notation probably cannot be
> exactly as shown above, but I hope there is a way to do it.

I think an argument should be _either_ named _or_ positional.
This would also allow overloading on argument names.

Example:

class Complex
{
public:
  Complex(double x, double y = 0): re(x), im(y) {}
  Complex(re: double = 0, im: double = 0): re(re), im(im) {}
  Complex(abs: double = 1, arg: double):
    re(abs * cos(arg)), im(abs* sin(arg)) {}
  // ...
private:
  double re, im;
};

Complex a, // 0
        b(1.5), // 1.5
        c(2.2, 1.7), // 2.2 + 1.7i
        d(abs:2, arg: 3), // 2*e^(3i)
        e(arg: 1.7), // e^(1.7i)
        f(re: 5), // 5
        g(im: 2), // 2i
        h(im: 7, re: 8); // 8+7i

The ":" versions are named arguments.

Of course, named and unnamed arguments may be used in the same
signature. In calls, arguments without "foo:" are matched up with
positional arguments, and arguments with "foo:" match the
corresponding named arguments.

One has to be careful not to create ambiguities (f.ex. in the
Complex class, only the second constructor can be used as
default constructor; if the first one had a default argument
on the first positional argument, then the definition of a
would be ambiguous.

For operators, there's a possible ambiguity with labels:

T operator+(foo: T, T);

foo: T() + T();
// Label or argument name?

This should be resolved as label.
To get the named argument, one would have to write

(foo: T() + T());

---
[ 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    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: "Radoslav Getov" <nospam@mai.com>
Date: Wed, 9 May 2001 20:46:49 GMT
Raw View
"Dennis Yelle" <dennis51@jps.net> wrote in message
news:3AEF1353.87673842@jps.net...
> So, what do we want?
>
[snip]

How about named argument funciton calls? I know it would be too large a
step, but anyway:

In Ada (I think) it's possible to do this:

void rotate (double x, double y, double rotation);

rotate  (rotation = Pi, x = y = 0 ); // the same as rotate (0, 0, Pi)
rotate  (0, 0, rotation = Pi); // still the same

rotate  (1, 2, z = 5) // error here - 'z' - no such argument name
rotate  (1, 2, x = 5) // error here - 'x' already passed by position

Justification:
- positional arguments calls tend to be buggy, especially if arguments are
of
same (or similar) types
- improving readability; e.g. 'func (check_it <= true)' is much more
clear (at the point of call) than just func (true);

Surely for the purpose of compatibility the notation probably cannot be
exactly as shown above, but I hope there is a way to do it.

Just an idea.

Radoslav Getov



---
[ 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    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]