Topic: PROPOSAL: More flexible initializer syntax.


Author: Christopher Eltschka <celtschk@physik.tu-muenchen.de>
Date: 1996/11/29
Raw View
Pete Becker wrote:
>
> Dave Toland wrote:
> >
> > Christian Bau <christian.bau@isltd.insignia.com> wrote:
> > >If any of these suggestions should become a proposal for the C++ standard
> > >or the C standard, I would very much like a syntax that has a chance to
> > >be extended to function argument lists. For example:
> > >
> > >/* Declaration */
> > >extern void MoveTo (short h, short v);
> > >
> > >/* Trying to call it. Now was it h, v or x, y? */
> > >MoveTo (x: 100, y: 200); /* Compiler tells me I was wrong. */
> > >MoveTo (h: 200, v: 100); /* Compiler sees I was right */
> > >MoveTo (v: 100, h: 200); /* Compiler sorts it out for me */
> > >
> > >In this situation a syntax using "=" cannot be used.
> >
> > There is an aspect of this I really don't like.
>
> There's another aspect of this that I really don't like: how does it
> ineract with overloading? We considered a couple of proposals, and some
> folks worked hard on this, but nobody could make it work sensibly with
> overloading.

What about the following solution?

Use an additional declaration syntax like this:

int f(double length: l, double heigth: h);
      // f has named arguments "length" (var. l) and "heigth" (var. h)

The argument names (the names before ':') would be part of the
signature, so this would be a  completely different function than

int f(double l, double h);

which would not have any named identifiers. This way you would not
break any code. If you want to let the user choose to use/not use
the named arguments, you would declare f.ex.

int f(double l, double h);

inline int f(double length: l, double height: h)
{
  f(l,h); // calls the non-named-arguments function
}

The calling syntax for the named-arguments function would be
straightforward:

f(length: 1.5, heigth: 3); // calls f(double length:l, double height:h)
                           // with l=1.5 and h=3 (which in turn calls
                           // f(1.5, 3) because of its definition)
f(height: 3, length: 1.5); // calls f(double length:l, double height:h)
                           // with l=1.5 and h=3
f(1.5,3);                  // calls f(double l,double h)
                           // with l=1.5 and h=3

The general syntax would be:

If a function has non-named arguments, those have to be given
  in order. Default arguments are handled as usual.
If a function has named arguments, they *have* to be named
  at any call. The order of named arguments does not matter, nor does
  the relative order between named and non-named arguments.
  Default and non-default named arguments can appear in any order.
  The argument name may, but needs not to be the same as the var name.

Of course, no two signatures may "collapse", if default parameters
are omitted, thus:

void f(int i=0) { ... }
void f(int param: x=1) { ... }

int main()
{
  f(); // f(int) or f(int param:)?
}

is not allowed. But that's nothing new anyway.

There are two additional points to mention if this syntax is to be
used with operators.

The first one concerns labels:

As C++ lables are declared as "identifier:", you must deal with
the situation

int a;
xy: a++; // label xy, call to operator++(int)
         // or call to operator++(int xy:)?

But this can easily be resolved by a rule that enforces to use
brackets for the second alternative:

xy: a++;   // label xy, call to operator++(int&) (as in current C++)
(xy: a)++; // call to operator++(int& xy:) (syntax invalid in current
C++)

This is quite similar to the parameter/ komma operator situation:

void f(int);
void f(int,int);

f(1,2);     // call to f(int,int)
f( (1,2) ); // call to f(int) with comma operator.

The second one is the case of combined operators:

a= xy: b * c + d; // operator+(operator*(xy: b, c), d)
                  // or operator+(xy: operator*(b,c), d)?

This can be addressed by the rule that parameter naming binds stronger
than any operator, thus the expression above is equivalent to

a= (xy: b)*c+d; // operator+(operator*(xy: b, c), d)

in opposite to

a= xy:(b*c)+d; // operator+(xy: operator*(b,c), d)


A few examples:

void f(int x, double y, char xy: pc, int* vw: pi);
                                // declare a function (1)
void f(int, double, int* vw:, char xy:);
                                // redeclare the same function (1)
void f(double, int, char xy:, int* vw:);
                                // declare another function (2)
void f(int, int* vw:, double, char xy:);
                                // redeclare function (1)
void f(int x, double y, char, int* vw:);
                                // declare a new function (3);

char ch;
double dbl;
int i;

f(i, dbl, xy: ch, vw: &i); // calls function (1)
f(i, dbl, vw: &i, xy: ch); // calls function (1)
f(dbl, vw: ch, vw: &i, i); // calls function (2)
f(i, dbl, ch, vw: &i);     // calls function (3)

void g(int length: length);
      // signature name and variable name may be the same

Ok, this was just for illustration of the way it would work
(hopefully no one would write such awful code :-) ).

Now some places where it would be useful:

class complex
{
  double Re, Im;
public:
  complex(double re, double im=0) : Re(re), Im(im) {}
             // just the usual constructor, but doesn't cover
             // the default case
  complex(double re:re=0, double im:im=0): Re(re), Im(im) {}
             // so you can init it as complex(re: 2, im:5),
             // as complex(re: 3.5), and as complex (im: 4).
             // Includes the default constructor.
  complex(double radius: r=1, double argument: phi):
            Re(r*cos(phi)), Im(r*sin(phi));
             // so you can initialize it with
             // complex(radius: 5, argument: M_PI/4) (gives 5*e^(i*pi/4)
)
             // or with complex(argument: M_PI/6) ( gives e^(i*pi/6) )
// ...
};

template<class T> class array
{
  int min, max;
  T* t;
public:
// ... usual constructors
  array(const array& a): min(a.min), max(a.max) { t=copy_of(T* t); }
  array(const array& flat: a): min(a.min, max(a.max), t(a.t) {}
  T& operator[](int i) { return t[i-min]; }
  T& operator[](int checked: i)
    { if( i<min || i>max ) throw Range; return (*this)[i]; }
// ...
};

int main()
{
  array<int> a;
  array b(a); // normal copy constructor called
  array c(flat: a); // make flat copy
  a[4]=2; // quick, unchecked subscripting
  a[checked: 6]=5; // subscripting with check
  return 0;
};

With this approach, you'd get on the one hand:

- no problem with old code (as the declarations differ)
- no problem with different variable names (as parameter names
  and variable names may differ)
- no problem with overloading (as the parameter name - unlike the var
  name - is part of the signature)

On the other hand you get:

- named arguments (wich are nice in some circumstances)
- a new possibility to select between different parameter sets
  with the same types, without being forced to define helper
  types for that purpose (which is especially interesting for
  functions which would normally look like
  enum action { a1, a2, a3 };
  void f(int i, action a=a1);
  where action isn't used anywhere else in the code,
  and in situations where different number of parameters isn't
  allowed (the operator[] example above))

I don't see any problems with this way of argument naming.
Anything I'm missing?
---
[ 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                             ]





Author: Julian Pardoe <pardoej@lonnds.ml.com>
Date: 1996/11/01
Raw View
Dave Toland wrote:
> Christian Bau <christian.bau@isltd.insignia.com> wrote:
> >If any of these suggestions should become a proposal for the C++ standard
> >or the C standard, I would very much like a syntax that has a chance to be
> >extended to function argument lists. For example:
> >
> >/* Declaration */
> >extern void MoveTo (short h, short v);
> >
> >/* Trying to call it. Now was it h, v or x, y? */
> >MoveTo (x: 100, y: 200); /* Compiler tells me I was wrong. */
> >MoveTo (h: 200, v: 100); /* Compiler sees I was right */
> >MoveTo (v: 100, h: 200); /* Compiler sorts it out for me */
> >
> >In this situation a syntax using "=" cannot be used.

I've always preferred a syntax using ":"!  I always wanted aggregates
to support this syntax too.  (I wanted to write { foo: 27 } rather
than the { .foo = 27 } that we're going to get!)

> There is an aspect of this I really don't like.  Up until now, the naming
> of the arguments to a function was not part of the function specification,
> and with this proposal that will no longer be the case.  Is the benefit
> of keyworded argument lists sufficient to offset the additional porting
> headaches?
>
> Keep in mind that legacy libraries will still be in widespread use, and
> that anyone who develops an application using this new feature with legacy
> libraries will cause problems for anyone porting to another system which
> may have an otherwise compatible legacy library with either different or
> omitted argument names for the same arguments of common functions.

This is indeed the crux of the problem -- though not because of any
porting or backwards-compatibility issues.  (I find your examples a little
contrived.)

The problem is that up to now it has been quite legal to have
    void Copy (Point from, Point to);
in one header and
    void Copy (Point src, Point dst);
in another.  The argument names can also vary between function declaration
and function definition (itself a declaration).

If two or more conflicting declarations are in scope which names should be
used?

I think this is covered in D&E!  I once asked BS about this one: he became
exasperated!

> I also see additional difficulties arising if the function is overloaded,
> since now determination of the correct signature to select has become
> more likely to become ambiguous, which could potentially make many existing
> libraries unusable.

Why?  You could use the current rules and simply ignore argument names when
resolving the overloading.  Once a particular function has been picked then
worry about the names.

> To me, this feature is just a gaudy piece of decorative scrollwork that
> pretends to compensate for a user's poor understanding of the function
> signature.

I don't understand this argument at all.  Are identifiers longer than
6 characters "decorative scrollwork"?  When I'm reading a new piece of
code I can't be expected to have an encyclopaedic knowledge of the entire
system and I certainly don't want to go away and read the definition of
every function that the code I'm looking at calls.  Keyed arguments are
a handy piece of self-documentation just like meaningful function-names.
When a function takes several arguments of the same type or a very large
number of arguments using keyed arguments cuts out a source of bugs as
well as being informative.  If I see the call
    Copy (foo, bar);
I can't immediately tell what is being copied to where.  If I see:
    Copy (from: foo, to: bar);
I know exactly what's going on -- and it's a lot less likely that the
programmer made a mistake in which argument is which too!

Keyed arguments also allow a more flexible form of argument defaulting.
This too can be extremely useful when a function takes a large number
of arguments.

-- jP --



[ 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                             ]





Author: Pete Becker <pbecker@oec.com>
Date: 1996/11/02
Raw View
Dave Toland wrote:
>
> Christian Bau <christian.bau@isltd.insignia.com> wrote:
> >If any of these suggestions should become a proposal for the C++ standard
> >or the C standard, I would very much like a syntax that has a chance to be
> >extended to function argument lists. For example:
> >
> >/* Declaration */
> >extern void MoveTo (short h, short v);
> >
> >/* Trying to call it. Now was it h, v or x, y? */
> >MoveTo (x: 100, y: 200); /* Compiler tells me I was wrong. */
> >MoveTo (h: 200, v: 100); /* Compiler sees I was right */
> >MoveTo (v: 100, h: 200); /* Compiler sorts it out for me */
> >
> >In this situation a syntax using "=" cannot be used.
>
> There is an aspect of this I really don't like.

There's another aspect of this that I really don't like: how does it
ineract with overloading? We considered a couple of proposals, and some
folks worked hard on this, but nobody could make it work sensibly with
overloading.
---
[ 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                             ]





Author: bradds@concentric.net (Bradd W. Szonye)
Date: 1996/11/06
Raw View
Julian Pardoe <pardoej@lonnds.ml.com> wrote in article
<327A49AA.6A77@lonnds.ml.com>...
> Dave Toland wrote:
[about named function arguments]

> > There is an aspect of this I really don't like.  Up until now, the
naming
> > of the arguments to a function was not part of the function
specification,
> > and with this proposal that will no longer be the case.  Is the benefit
> > of keyworded argument lists sufficient to offset the additional porting
> > headaches?
> >
> > Keep in mind that legacy libraries will still be in widespread use, and
> > that anyone who develops an application using this new feature with
legacy
> > libraries will cause problems for anyone porting to another system
which
> > may have an otherwise compatible legacy library with either different
or
> > omitted argument names for the same arguments of common functions.
>
> This is indeed the crux of the problem -- though not because of any
> porting or backwards-compatibility issues.  (I find your examples a
little
> contrived.)

Actually, it's not totally contrived. Sometimes people keep all function
prototypes the same when porting, but that isn't necessarily the case.
Sometimes the port is actually a partial or complete re-write (possibly by
different people), and then the prototypes are unlikely to match in the
spelling of argument names.

> The problem is that up to now it has been quite legal to have
>     void Copy (Point from, Point to);
> in one header and
>     void Copy (Point src, Point dst);
> in another.  The argument names can also vary between function
declaration
> and function definition (itself a declaration).

Or, even worse

 char* strcpy(char*, const char*);
 char* strcpy(char* s1, const char*);
 char* strcpy(char* lhs, const char* rhs);

in three different vendors' libraries. Not only must the names match from
header to header, they must also match from vendor to vendor and from
header to implementation. Many corporate standards take advantage of the
fact that the names need not be the same (or even present). Do you really
want the C++ standard bogged down in arguments over what the
function-parameter names should be?

> If two or more conflicting declarations are in scope which names should
be
> used? I think this is covered in D&E!  I once asked BS about this one: he
became
> exasperated!

And for good reason. The extension breaks a lot of existing code and makes
code maintenance much more difficult, because you must guarantee that
declarations in widely-separated locations must all match. It's no longer
sufficient to look in one place to see that an argument name is valid.
Also, the extension encourages sloppy programming and unmaintainable
styles, which I go into below.

> > I also see additional difficulties arising if the function is
overloaded,
> > since now determination of the correct signature to select has become
> > more likely to become ambiguous, which could potentially make many
existing
> > libraries unusable.
>
> Why?  You could use the current rules and simply ignore argument names
when
> resolving the overloading.  Once a particular function has been picked
then
> worry about the names.

You can't ignore the argument names, if they're given. Even if they're not
given, the compiler still has to "mangle" the names into the signature
somehow. If something doesn't match correctly, it's harder to give a
sensible diagnostic. If the compiler doesn't mangle in the names, then
other subtle inconsistencies and ambiguities can creep in.

> > To me, this feature is just a gaudy piece of decorative scrollwork that
> > pretends to compensate for a user's poor understanding of the function
> > signature.

I agree.

Article Unavailable




Author: Dave Toland <det@platsol.com>
Date: 1996/11/01
Raw View

Christian Bau <christian.bau@isltd.insignia.com> wrote:
>If any of these suggestions should become a proposal for the C++ standard
>or the C standard, I would very much like a syntax that has a chance to be
>extended to function argument lists. For example:
>
>/* Declaration */
>extern void MoveTo (short h, short v);
>
>/* Trying to call it. Now was it h, v or x, y? */
>MoveTo (x: 100, y: 200); /* Compiler tells me I was wrong. */
>MoveTo (h: 200, v: 100); /* Compiler sees I was right */
>MoveTo (v: 100, h: 200); /* Compiler sorts it out for me */
>
>In this situation a syntax using "=" cannot be used.

There is an aspect of this I really don't like.  Up until now, the naming
of the arguments to a function was not part of the function specification,
and with this proposal that will no longer be the case.  Is the benefit
of keyworded argument lists sufficient to offset the additional porting
headaches?

Keep in mind that legacy libraries will still be in widespread use, and
that anyone who develops an application using this new feature with legacy
libraries will cause problems for anyone porting to another system which
may have an otherwise compatible legacy library with either different or
omitted argument names for the same arguments of common functions.

I also see additional difficulties arising if the function is overloaded,
since now determination of the correct signature to select has become
more likely to become ambiguous, which could potentially make many existing
libraries unusable.

To me, this feature is just a gaudy piece of decorative scrollwork that
pretends to compensate for a user's poor understanding of the function
signature.

--
Home is within you.
Dave Toland          PLATINUM Solutions, Inc.     det@platsol.com


[ 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                             ]





Author: ccshan@husc.harvard.edu (Chung-chieh Shan)
Date: 1996/10/17
Raw View
Max TenEyck Woodbury (mtew@cds.duke.edu) wrote:
>     struct x_tag {
>         int a;
>         float b;
>         } x { b = 10.5, a = 987 };

As a side comment, the above syntax is ambiguous:

    int a;
    float b;
    struct x_tag x { b = 10.5, a = 987 };
        // assignment to b and a, or reference to struct members?

To be unambiguous and consistent with the [] syntax for initializing
arrays, we should have:

    struct x_tag x { .b = 10.5, .a = 987 };

That, however, raises the question of whether

    struct y_tag {
        int a[3];
        float b;
    } y { .a[1] = 2, .a[0] = 3, .b = 4.2, .a[2] = 5 };

should be allowed.

--
blue | Ken; Shan, Chung-chieh; Sian7, Tiong1-kiat8; ccshan@fas.harvard.edu.
 ()  | Your code today becomes the mind tomorrow:  Your plan its means,
 /\  | your dream its ends, your ideal its elegance.  Hack on.


[ 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                             ]





Author: christian.bau@isltd.insignia.com (Christian Bau)
Date: 1996/10/18
Raw View
In article <3265125D.5A68@cds.duke.edu>, Max TenEyck Woodbury
<mtew@cds.duke.edu> wrote:

> J. Kanze wrote:
> > In cases like the above, I would prefer a different approach: being able
> > to specify the index of the element I want to initialize (maybe with a
> > default), thus:
> >
> >     char const* const sys_errlist[]
> >     {
> >         case NOERROR : "No error" ,
> >         case E2BIG :   "File outgrew its dress size" ,
> >         case EBADF :   "Bad Fido" ,
> >         //  ...
> >         default :      "Unknown error code"
> >     } ;
> >
> > This way, you don't get screwed when some idiot ups and changes the enum.
>
> Maybe an alternate syntax would work a bit better.  How about
>
>     char const* const sys_errlist[MAX_ERR] {
>         []        = "Unknown error code",   // default value
>         [NOERROR] = "No error",
>         [E2BIG]   = "file outgrew its dress size",
>         [EBADF]   = "Bad Fido",
>         // ...
>     };
>
> That could be tied to a way to initialize members of a structure that
> would be independent of the order of declaration of the elements.
>
>     struct x_tag {
>         int a;
>         float b;
>         } x { b = 10.5, a = 987 };

If any of these suggestions should become a proposal for the C++ standard
or the C standard, I would very much like a syntax that has a chance to be
extended to function argument lists. For example:

/* Declaration */
extern void MoveTo (short h, short v);

/* Trying to call it. Now was it h, v or x, y? */
MoveTo (x: 100, y: 200); /* Compiler tells me I was wrong. */
MoveTo (h: 200, v: 100); /* Compiler sees I was right */
MoveTo (v: 100, h: 200); /* Compiler sorts it out for me */

In this situation a syntax using "=" cannot be used.
---
[ 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: kanze@gabi-soft.fr (J. Kanze)
Date: 1996/10/18
Raw View
Max TenEyck Woodbury <mtew@cds.duke.edu> writes:

> J. Kanze wrote:
> >
> > ...
> >
> > In cases like the above, I would prefer a different approach: being able
> > to specify the index of the element I want to initialize (maybe with a
> > default), thus:
> >
> >     char const* const sys_errlist[]
> >     {
> >         case NOERROR : "No error" ,
> >         case E2BIG :   "File outgrew its dress size" ,
> >         case EBADF :   "Bad Fido" ,
> >         //  ...
> >         default :      "Unknown error code"
> >     } ;
> >
> > This way, you don't get screwed when some idiot ups and changes the enum.
>
> Maybe an alternate syntax would work a bit better.  How about
>
>     char const* const sys_errlist[MAX_ERR] {
>         []        = "Unknown error code",   // default value
>         [NOERROR] = "No error",
>         [E2BIG]   = "file outgrew its dress size",
>         [EBADF]   = "Bad Fido",
>         // ...
>     };
>
> That could be tied to a way to initialize members of a structure that
> would be independent of the order of declaration of the elements.
>
>     struct x_tag {
>         int a;
>         float b;
>         } x { b = 10.5, a = 987 };
>
> The main problem would be that one pass compilers with stupid linkers
> might not be able to implement the out-of-order initialization, and the
> inclusion of this kind of feature would force some implementation issues
> that might not otherwise arise.  This argument might work with C, but
> there are enough features in C++ (drop in declarations and templates)
> that preclude one pass compilers and simple minded linkers.

FWIW: there is a proposal for exactly this (except that the structure
tags must be preceded by a .) before the C standards committee.  See
<URL:http://www.dmk.com/c/init.html>

In comparison with my suggestion, it lacks a default case and multiple
cases.  On the other hand, they can (easily?) be added, and it supports
struct and union.  I'll admit that I prefer my syntax, with big fat
juicy keywords up front, to tell the parser (be it in the compiler, or
in a human reader's head) what is going on.  The extension to struct
members is a powerful argument, however.

--
James Kanze           (+33) 88 14 49 00          email: kanze@gabi-soft.fr
GABI Software, Sarl., 8 rue des Francs Bourgeois, 67000 Strasbourg, France
Conseils en informatique industrielle --
                            -- Beratung in industrieller Datenverarbeitung
---
[ 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: jcoffin@taeus.com (Jerry Coffin)
Date: 1996/10/19
Raw View
In article <3265125D.5A68@cds.duke.edu>, mtew@cds.duke.edu says...

[ ... ]

> That could be tied to a way to initialize members of a structure
> that would be independent of the order of declaration of the
> elements.
>
>     struct x_tag {
>         int a;
>         float b;
>         } x { b = 10.5, a = 987 };
>
> The main problem would be that one pass compilers with stupid
> linkers might not be able to implement the out-of-order
> initialization, and the inclusion of this kind of feature would
> force some implementation issues that might not otherwise arise.

I don't see where this would cause a problem with one-pass
compilation, as long as the member was required to be defined prior to
use or initialization.

However, I'm not sure how you'd use this in conjunction with
initializers in a ctor.  Would any initializer in the ctor override
this initializer?  Would having two different initializers, one in the
ctor and one in place be illegal, possibly give undefined results, or
be legal with well defined results?

Would the order of initialization defined here also be used as the
order of initialization used by initializers in a ctor, or would the
order used there still be the order of declaration?

> This argument might work with C, but there are enough features in
> C++ (drop in declarations and templates) that preclude one pass
> compilers and simple minded linkers.

Offhand the lack of ctors in C seems to me to simplify implementation
there.  This more or less directly conflicts with initialization in a
ctor.

--
    Later,
    Jerry.


[ 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                             ]





Author: dacut@ugcs.caltech.edu (David A. Cuthbert)
Date: 1996/10/21
Raw View
Christian Bau <christian.bau@isltd.insignia.com> wrote:
>If any of these suggestions should become a proposal for the C++ standard
>or the C standard, I would very much like a syntax that has a chance to be
>extended to function argument lists. For example:
>
>/* Declaration */
>extern void MoveTo (short h, short v);
>
>/* Trying to call it. Now was it h, v or x, y? */
>MoveTo (x: 100, y: 200); /* Compiler tells me I was wrong. */
>MoveTo (h: 200, v: 100); /* Compiler sees I was right */
>MoveTo (v: 100, h: 200); /* Compiler sorts it out for me */
>
>In this situation a syntax using "=" cannot be used.

I like this idea; I also see another logical extension which is
similar, mostly applicable to units of measure.

For example, extending the MoveTo calls above:

   MoveTo(v: 100 cm, h: 200 cm)
   MoveTo(h: 72 pt, v: -25 mile)

Let's say that the programmer implemented MoveTo in terms of inches.
Then, the decl for MoveTo would look like:

   MoveTo(length v inch, length h inch)

where length is a class of sorts (which may have yet another internal
representation, such as furlongs or whatever).

There is a workaround for this in C++, but it isn't very pretty.

Even as useful as these changes would be, they do not add any
functionality to the language, and therefore don't really solve
anything that can't already be solved.  I do think, however, that such
an idea would be useful for another (perhaps more end-user oriented)
language (which may be implemented only as a front-end to C++).

--
David A. Cuthbert
dacut@ugcs.caltech.edu
---
[ 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: comeau@panix.com (Greg Comeau)
Date: 1996/10/09
Raw View
In article <01bbb568$c75233a0$31d8cac6@chico> "Daniel Pflager" <dpflag@ix.netcom.com> writes:
>My proposal is to add a "repetition factor" to any initializer using the *
>as follows:
>
>char* sys_errlist[] =
> {
> "No error",
> "File Outgrew its Dress Size",
> 22 * { 0 },
> "Bad Fido",
> "Bad Domino's Pizza",
> "Bad Existence for Life on Mars",
> ...
> };
>

This too has been proposed many times.  It's too late for C++ as there
is a feature freeze, however C9X (draft) _does_ have a similar mechanism
for doing things such as this, so perhaps parts of it will leak into
C++ compilers sooner or later.

- Greg
--
       Comeau Computing, 91-34 120th Street, Richmond Hill, NY, 11418-3214
 Here:comeau@csanta.attmail.com / BIX:comeau or comeau@bix.com / CIS:72331,3421
    Voice:718-945-0009 / Fax:718-441-2310 / Prodigy: tshp50a / WELL: comeau


[ 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                             ]





Author: kanze@gabi-soft.fr (J. Kanze)
Date: 1996/10/10
Raw View
"Daniel Pflager" <dpflag@ix.netcom.com> writes:

> I used to program on Tandem computers in a language like TAL. The language
> had some cute features which I miss in C/C++. One of them has to do with
> initializers. Quite often, I find myself creating tables of static data in
> order to do fast look-ups instead of calculations, and so on.
>
> Here's a little example of a table used by a function which converts errors
> to strings (like strerror() for example). I know this is not very C++-like,
> but I have lost all hope of anything like this happening to C.
>
> I am mixing things up here to make a point. Also, any resemblance between
> any identifiers used here and any standards is purely coincidental.
>
> This is what my old code would look like:
>
>
>
> enum errors
>  {
>  NOERROR = 0,
>  E2BIG = 1,
>  EBADF = 23,
>  EDOM,
>  EEXIST,
>
>  // and many others, with lots of big gaps of varying sizes
>
>  };
>
> char* sys_errlist[] =
>  {
>  "No error",
>  "File outgrew its dress size",
>  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
>  "Bad Fido",
>  "Bad Dominos",
>  "Bad Existence"
>  };
>
>
> My proposal is to add a "repetition factor" to any initializer using the *
> as follows:
>
> char* sys_errlist[] =
>  {
>  "No error",
>  "File Outgrew its Dress Size",
>  22 * { 0 },
>  "Bad Fido",
>  "Bad Domino's Pizza",
>  "Bad Existence for Life on Mars",
>  ...
>  };

Sort of like Fortran.  Can the repetition factors nest?

In cases like the above, I would prefer a different approach: being able
to specify the index of the element I want to initialize (maybe with a
default), thus:

    char const* const sys_errlist[]
    {
        case NOERROR : "No error" ,
        case E2BIG :   "File outgrew its dress size" ,
        case EBADF :   "Bad Fido" ,
        //  ...
        default :      "Unknown error code"
    } ;

This way, you don't get screwed when some idiot ups and changes the enum.

--
James Kanze           (+33) 88 14 49 00          email: kanze@gabi-soft.fr
GABI Software, Sarl., 8 rue des Francs Bourgeois, 67000 Strasbourg, France
Conseils en informatique industrielle --
                            -- Beratung in industrieller Datenverarbeitung
---
[ 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: Chelly Green <chelly@eden.com>
Date: 1996/10/14
Raw View
J. Kanze wrote:
>
> "Daniel Pflager" <dpflag@ix.netcom.com> writes:
>
...
> > enum errors
> >       {
> >       NOERROR = 0,
> >       E2BIG = 1,
> >       EBADF = 23,
> >       EDOM,
> >       EEXIST,
> >       // and many others, with lots of big gaps of varying sizes
> >       };
> >
> > char* sys_errlist[] =
> >       {
> >       "No error",
> >       "File outgrew its dress size",
> >       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
> >       "Bad Fido",
> >       "Bad Dominos",
> >       "Bad Existence"
> >       };
> >
> > My proposal is to add a "repetition factor" to any initializer using the *
> > as follows:
> >
> > char* sys_errlist[] =
> >       {
> >       "No error",
> >       "File Outgrew its Dress Size",
> >       22 * { 0 },
> >       "Bad Fido",
> >       "Bad Domino's Pizza",
> >       "Bad Existence for Life on Mars",
> >       ...
> >       };
>
> Sort of like Fortran.  Can the repetition factors nest?
>
> In cases like the above, I would prefer a different approach: being able
> to specify the index of the element I want to initialize (maybe with a
> default), thus:
>
>     char const* const sys_errlist[]
>     {
>         case NOERROR : "No error" ,
>         case E2BIG :   "File outgrew its dress size" ,
>         case EBADF :   "Bad Fido" ,
>         //  ...
>         default :      "Unknown error code"
>     } ;
>
> This way, you don't get screwed when some idiot ups and changes the enum.
...

But isn't this just  trying to get the language to support a map of
error codes to error strings? When I need something like this, I just
use a table:

    typedef int Error;

    const Error NOERROR = 0;
    const Error E2BIG = 1;
    const Error EBADF = 2;

    struct ErrorToString {
        int error;
        const char* string;
    };

    static const ErrorToString sys_errlist [] = {
        NOERROR,    "No Error",
        E2BIG,      "File outgrew its dress size",
        EBADF,      "Bad Fido",
        //  ...
        -1, "Unknown error code"
    };

    const char* err_to_string( int error )
    {
        const ErrorToString* cur = sys_errlist;
        while ( cur->error != -1 && cur->error != error )
            ++cur;
        return cur->string;
    }

// test driver

    #include <assert.h>
    #include <string.h>
    #include <iostream.h>

    int main()
    {
        assert( strcmp( err_to_string( 1234 ), "Unknown error code" ) ==
0 );
        assert( strcmp( err_to_string( NOERROR ), "No Error" ) == 0 );
        assert( strcmp( err_to_string( E2BIG ), "File outgrew its dress
size" ) == 0 );

        cout << err_to_string( EBADF ) << endl;

        return 1;
    }

Or heck, your example looked almost like a switch statement. Why not
just write it is that, and let the compiler optimize the lookup (binary
search, maybe)?
--
Chelly Green | chelly@eden.com | C++ - http://www.eden.com/~chelly
---
[ 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: bill@amber.ssd.csd.harris.com (Bill Leonard)
Date: 1996/10/14
Raw View
In article <m3g23nnrqr.fsf@gabi-soft.fr>, kanze@gabi-soft.fr (J. Kanze) writes:
> In cases like the above, I would prefer a different approach: being able
> to specify the index of the element I want to initialize (maybe with a
> default), thus:
>
>     char const* const sys_errlist[]
>     {
>         case NOERROR : "No error" ,
>         case E2BIG :   "File outgrew its dress size" ,
>         case EBADF :   "Bad Fido" ,
>         //  ...
>         default :      "Unknown error code"
>     } ;
>
> This way, you don't get screwed when some idiot ups and changes the enum.

Not only that, but you can also initialize arrays indexed by enums or
#define constants that you don't control and don't necessarily know the
ordering of.  For instance, in the application I work on (a debugger), I
need arrays indexed by signal numbers.  However, the signal numbers (and
their ordering) vary from one version of Unix to another, and some versions
define signals that others don't.  I finally just gave up and resorted to
initializing the arrays at runtime so that my code was cleaner and less
OS-dependent.  However, if I'd had the above feature, I could have cleanly
(and with ifdefs, portably) initialized my arrays statically.

I like Mr. Kanze's suggestion the best.  I hope the next revision of the
standard will consider this.

--
Bill Leonard
Concurrent Computer Corporation
2101 W. Cypress Creek Road
Fort Lauderdale, FL  33309
Bill.Leonard@mail.ccur.com

These opinions and statements are my own and do not necessarily reflect the
opinions or positions of Concurrent Computer Corporation.
---
[ 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: kanze@gabi-soft.fr (J. Kanze)
Date: 1996/10/15
Raw View
Chelly Green <chelly@eden.com> writes:

> J. Kanze wrote:

    [...]
> > In cases like the above, I would prefer a different approach: being able
> > to specify the index of the element I want to initialize (maybe with a
> > default), thus:
> >
> >     char const* const sys_errlist[]
> >     {
> >         case NOERROR : "No error" ,
> >         case E2BIG :   "File outgrew its dress size" ,
> >         case EBADF :   "Bad Fido" ,
> >         //  ...
> >         default :      "Unknown error code"
> >     } ;
> >
> > This way, you don't get screwed when some idiot ups and changes the enum.
> ...
>
> But isn't this just  trying to get the language to support a map of
> error codes to error strings?

Yes:-).  Of course, it isn't just error codes that sometimes need
mapping.  All sorts of enums occur in practice.  And the mapping isn't
just to strings; in fact, typically, it will be to pointers to objects.

> When I need something like this, I just
> use a table:

I mostly use the equivalent of an STL map; I derive from the map to make
it a singleton (with the sole instance write protected) and initialize
the table.

> Or heck, your example looked almost like a switch statement. Why not
> just write it is that, and let the compiler optimize the lookup (binary
> search, maybe)?

The resemblance to switch is intentional.  I don't want a switch
statement, because I don't want the switch scattered all over the code;
when more values are introduced, I want to just modify one single place:
the table.

In fact, given map, the above is really just a minor convenience in
C++.  Where it would really be nice is in C.

--
James Kanze           (+33) 88 14 49 00          email: kanze@gabi-soft.fr
GABI Software, Sarl., 8 rue des Francs Bourgeois, 67000 Strasbourg, France
Conseils en informatique industrielle --
                            -- Beratung in industrieller Datenverarbeitung


[ 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                             ]





Author: Max TenEyck Woodbury <mtew@cds.duke.edu>
Date: 1996/10/16
Raw View
J. Kanze wrote:
>
> ...
>
> In cases like the above, I would prefer a different approach: being able
> to specify the index of the element I want to initialize (maybe with a
> default), thus:
>
>     char const* const sys_errlist[]
>     {
>         case NOERROR : "No error" ,
>         case E2BIG :   "File outgrew its dress size" ,
>         case EBADF :   "Bad Fido" ,
>         //  ...
>         default :      "Unknown error code"
>     } ;
>
> This way, you don't get screwed when some idiot ups and changes the enum.

Maybe an alternate syntax would work a bit better.  How about

    char const* const sys_errlist[MAX_ERR] {
        []        = "Unknown error code",   // default value
        [NOERROR] = "No error",
        [E2BIG]   = "file outgrew its dress size",
        [EBADF]   = "Bad Fido",
        // ...
    };

That could be tied to a way to initialize members of a structure that
would be independent of the order of declaration of the elements.

    struct x_tag {
        int a;
        float b;
        } x { b = 10.5, a = 987 };

The main problem would be that one pass compilers with stupid linkers
might not be able to implement the out-of-order initialization, and the
inclusion of this kind of feature would force some implementation issues
that might not otherwise arise.  This argument might work with C, but
there are enough features in C++ (drop in declarations and templates)
that preclude one pass compilers and simple minded linkers.

mtew@cds.duke.edu
---
[ 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: "Daniel Pflager" <dpflag@ix.netcom.com>
Date: 1996/10/08
Raw View
Hi,

I used to program on Tandem computers in a language like TAL. The language
had some cute features which I miss in C/C++. One of them has to do with
initializers. Quite often, I find myself creating tables of static data in
order to do fast look-ups instead of calculations, and so on.

Here's a little example of a table used by a function which converts errors
to strings (like strerror() for example). I know this is not very C++-like,
but I have lost all hope of anything like this happening to C.

I am mixing things up here to make a point. Also, any resemblance between
any identifiers used here and any standards is purely coincidental.

This is what my old code would look like:



enum errors
 {
 NOERROR = 0,
 E2BIG = 1,
 EBADF = 23,
 EDOM,
 EEXIST,

 // and many others, with lots of big gaps of varying sizes

 };

char* sys_errlist[] =
 {
 "No error",
 "File outgrew its dress size",
 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 "Bad Fido",
 "Bad Dominos",
 "Bad Existence"
 };


My proposal is to add a "repetition factor" to any initializer using the *
as follows:

char* sys_errlist[] =
 {
 "No error",
 "File Outgrew its Dress Size",
 22 * { 0 },
 "Bad Fido",
 "Bad Domino's Pizza",
 "Bad Existence for Life on Mars",
 ...
 };

This repetition factor would have to be a constant value, of course, but
could equally apply to groups of initializers as illustrated following:

char* sys_errlist[] =
 {
 "No error",
 "File outgrew its dress size",
 22 * {'E', 'm', 'p', 't', 'y', '\0'},
 "Bad Fido",
 "Bad Dominos",
 "Bad Existence",
 ...
 };

That's it...

Does anyone else think this is a good idea?

Salut,

Dan
---
[ 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
]