Topic: proposal : keyword default


Author: brangdon@cix.co.uk (Dave Harris)
Date: Sat, 15 Dec 2001 08:52:10 CST
Raw View
boris.bralo@zg.tel.hr (Boris Bralo) wrote (abridged):
> Is this look too complicated?

Yes, in my view. Partly because I think the benefit to the language from
allowing "default" in expressions is very small. It is not a feature I
would expect to use myself often, or indeed ever; I don't miss not having
it today.

The impact of allowing "default" not in expressions is much smaller. Also
it seems a bit sounder. If I call:

    proc( 42, default, 99 );

then I am only interested in the third argument, not the second. I would
be just as happy if the original functions had its last two arguments
swapped, so I could say:

    proc( 42, 99 );

and not need the "default" at all. Where-as if I write:

    proc( 42, default|1, 99 );

then I /am/ interested in the second argument. Maybe this would be better
written by introducing a constant called proc_default, or similar.

  Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
      brangdon@cix.co.uk      |   And close your eyes with holy dread,
                              |  For he on honey dew hath fed
 http://www.bhresearch.co.uk/ |   And drunk the milk of Paradise."

---
[ 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: "Boris Bralo" <boris.bralo@zg.tel.hr>
Date: Mon, 10 Dec 2001 16:47:22 GMT
Raw View
Hi Dave,
>"Dave Harris" <brangdon@cix.co.uk> wrote
> boris.bralo@zg.tel.hr (Boris Bralo) wrote (abridged):
> > By my opinion, the most straightforward implementaition is to do
> > "default" expansion as soon as is possible , somewhere early
> > in processing of entity. It may be even done by preprocessor, but
> > don't hold me on that, C++ preprocessor is busy enough.
>
> It can't be done before overload resolution. Eg:
>
>     void proc( int x, int y=INT_MAX );
>     void proc( long x, long y=LONG_MAX );
>
>     void demo() {
>        // ... some code which declares 'x'.
>        proc( x, default );
>     }
>

You're right.
In plain English: figure out what the function is and than deal with it.


> The value for default depends on the type of x and on which overloaded
> function is the best match for that type. I don't think we can tell what
> it is without a full parse. That's my point, really: it's *hard* to figure
> out what the code means.
>
>
> > > Changing the type of the first argument changes the type injected
> > > into the middle of the last expression, which is a bit unobvious.
> > > (There are probably more pathological examples than I can think
> > > of right now.)
> >
> > I don't see any problem here. Expression evaluates to [...]
>
> I know the compiler can figure it out. I'm concerned about us poor humans.
> Consider:
>
>     double func( double );
>     int func( int );
>
>     void proc( int x, double y=1.0, int z=1 );
>
>     void demo() {
>         proc( 1, func(default), func(default) );
>     }
>
> Here the two function calls look identical, but they have totally
> different meanings - they invoke different functions. The meaning of
> "default" depends on context in a way unlike anything seen before in C++.
>


Yes, but the same holds for
proc( 1, func(), func() );

> By the way, have you thought about how many times "default" is evaluated,
> and whether it is an rvalue or a const? Eg:
>
>     class Complex {
>         // The usual maths stuff here.
>     };
>     Complex func( Complex *pComplex );
>
>     void proc( int x, Complex y=Complex(0,0) );
>
>     void demo() {
>         proc( 0, func( &default ) );
>         proc( 0, default * default.negate() + (default = Complex(1,0)) );
>     }
I'm think of it as:
proc( 0, default * default.negate() + (default = Complex(1,0)) );
--->
{
    Complex def_arg = Complex(0,0);
    proc(int x, def_arg * def_arg.negate() + (def_arg = Complex(1,0)) );
   // OK but don't make any sense since arg is lost after call.
}
>
> I think the proposal is substantially simpler if we are not allowed to use
> "default" in expressions.
>
I agree.
I'm not even sure of utility of using default in expression.
It was stated as possible refinement in the original proposal,
but it generated most of the objections in this discussion.

Boris


---
[ 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: "Richard Smith" <richard@ex-parrot.com>
Date: Mon, 10 Dec 2001 16:49:47 GMT
Raw View
"Dave Harris" <brangdon@cix.co.uk> wrote in message
news:memo.20011207120912.49359D@brangdon.madasafish.com...
> richard@ex-parrot.com (Richard Smith) wrote (abridged):
> > Operator functions are not allowed to have default arguments [13.5/8],
> > the only exception is operator() [13.5.4/1], so this problem does
> > not arise.
>
> OK, but a similar problem arises with normal functions. The word "default"
> is being injected into expressions and its not at all obvious what it
> means in any given context.

OK, let's consider a modified version of the original example:

    void make_thread( thread_function* fp, void* params  =0, void* stack =
0,
                      long params = JOINABLE| NEW_LWP, thread_t* thr_id =
0 );

    enum Policy { SCHED_FIFO, ROUND_ROBIN, ... };
    int combine( int=ROUND_ROBIN, Policy=ROUND_ROBIN );

    make_thread( func, default, default, combine(default, SCHED_FIFO));
    //                                           ^^^^^^^

The question is what does the "default" passed to combine mean?  Does it
mean ROUND_ROBIN (the default of combine) or or does it mean
JOINABLE|NEW_LWP (the default 4th argument of make_thread?   I would argue
that it should mean the default argument of combine (i.e. ROUND_ROBIN).
Suppose combine is overloaded.  In a typical implementation, we resolve the
overloading of combine without knowing that the return value is going to be
passed as argument four of make_thread, and so we need to know the type of
"default" to resolve this.  The easiest way to ensure that it knows the type
of "default" would be to make "default" mean the "the default argument of
the innermost function"  (note: not "innermost function with a default
argument").

This would also mean that it is safe to assume that

    make_thread( func, default, default, combine(default, SCHED_FIFO));

and

    int combination = combine(default, SCHED_FIFO);
    make_thread( func, default, default, combination);

always mean the same.

One consequence of this would be that it is never legal to write,

    make_thread( func, default, default, default | SCHED_FIFO);

--
Richard Smith


---
[ 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: brangdon@cix.co.uk (Dave Harris)
Date: Mon, 10 Dec 2001 21:19:17 GMT
Raw View
boris.bralo@zg.tel.hr (Boris Bralo) wrote (abridged):
> > Here the two function calls look identical, but they have totally
> > different meanings - they invoke different functions. The meaning of
> > "default" depends on context in a way unlike anything seen before in
> > C++.
>
> Yes, but the same holds for
> proc( 1, func(), func() );

How so? This code gets its meaning in the usual "inside-out" way. Func()
is evaluated, then its result converted to whatever proc() needs. The
meaning of func() itself doesn't change.

  Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
      brangdon@cix.co.uk      |   And close your eyes with holy dread,
                              |  For he on honey dew hath fed
 http://www.bhresearch.co.uk/ |   And drunk the milk of Paradise."

---
[ 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: "Boris Bralo" <boris.bralo@zg.tel.hr>
Date: Tue, 11 Dec 2001 16:00:35 GMT
Raw View
Hi Dave,

It was my mistake - I was thinking as func() overloads have default value.

I proposed in this discussion that in default expansion comipiler looks for
first explict function call. In that case

proc( 1, func(default), func(default) );

would generate compile error becuse func has no default parameter.

The expresion "first explict function call" looks ugly but , before droping
the use of default
in expresions, I think we should consider this carefully:

Let the functions be :

void func(C c = C()); // C is some class
C g(C c);

a)    basic usage
       func( default ) ;
b)
      func( g(default));    // error,  g has no default parameters
c)   operators , except operator()()
      C other;
      func( default + other );                 // OK,  no explicit call to
operator+
d)
      func( operator+(default ,other) );

      Explicit call to operator+, but operators are not allowed to have
default arguments ([13.5/8]),
      so it's clear that default relates to func().
      I opt for treating this as c) i.e as there is no explicit call
e)  operator()()
     struct Functor {C operator ()(C c);}
     Functor f;

     func( f(default) );     //  error, operator() is allowed to have
default
                                    //   arguments ([13.5.4/1]),  but this
one has no one.

     i.e. I think that operator()() shoud be treated as ordinary function
call.

Is this look too complicated?

Boris


---
[ 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: Adam Peterson <ahp6@email.byu.edu>
Date: Tue, 11 Dec 2001 20:41:16 GMT
Raw View
<snip>
> Let the functions be :
>
> void func(C c = C()); // C is some class
> C g(C c);
>
> a)    basic usage
>        func( default ) ;
> b)
>       func( g(default));    // error,  g has no default parameters
> c)   operators , except operator()()
>       C other;
>       func( default + other );                 // OK,  no explicit call to
> operator+
> d)
>       func( operator+(default ,other) );
>
>       Explicit call to operator+, but operators are not allowed to have
> default arguments ([13.5/8]),
>       so it's clear that default relates to func().
>       I opt for treating this as c) i.e as there is no explicit call
> e)  operator()()
>      struct Functor {C operator ()(C c);}
>      Functor f;
>
>      func( f(default) );     //  error, operator() is allowed to have
> default
>                                     //   arguments ([13.5.4/1]),  but this
> one has no one.
>
>      i.e. I think that operator()() shoud be treated as ordinary function
> call.
>
> Is this look too complicated?
>

I think this may have a potential danger of encouraging misuse of operator
overloading to create functions that can pass through "default".  Misuse of
operator overloading is one of the most common complaints I hear against C++
from people who prefer other languages.




---
[ 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: "Pavel Kuznetsov" <su41vo7la001@sneakemail.com>
Date: Wed, 12 Dec 2001 19:15:21 GMT
Raw View
Radoslav Getov <rgetov@hotmail.com> wrote...
> While I personally think that default arguments are evil and try not
> to use ones, while we are there, why not allow <empty> arguments in
> function calls? E.G. something like
>
>     make_thread( func, , , , &id);
>
> IMO it's somewhat more consistent with what the default args are
> (i.e. something present but omitted and therefore using a default value).
>
> Might be the proposal using a keyword will be easier to parse, but
> I doubt that one would be so difficult either.


But then you wouldn't be able to write:

  make_thread(func, default, default, default | SCHED_FIFO);

or do you propose to allow:

  make_thread(func, , , | SCHED_FIFO);

--
Pavel Kuznetsov

[ THE REPLY ADDRESS IS NOT GUARANTEED TO LIVE LONGER THAN FEW WEEKS! ]
[ The permanent address is: pavel <dot> kuznetsov <at> mail <dot> ru ]


---
[ 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: "Boris Bralo" <boris.bralo@zg.tel.hr>
Date: Thu, 6 Dec 2001 18:42:26 GMT
Raw View
Hi Adam,
> I strongly object to any proposal that introduces significant differences
> between the two forms of calling an operator function.  I often call
> operator functions explicitly within my classes.

Operator functions are not allowed to have default arguments [13.5/8], the
only exception is operator() [13.5.4/1].
(see Dave Harris' post on this topic)

>
> I also think that the binding of default to innermost valid function needs
> to be rethought.
>
> Imagine:
>
>
> void f(int, int=1);
> void g(int=2);
> int main() {
>     g(f(1, default+1));
> }
>
>
> Now, someone changes
>     void f(int, int=1);
> to
>     void f(int, int);
>     void f(int);
>
> Suddenly, code changes meaning silently.  default is now bound to g's
> default, instead of f's.
>
I agree.
Maybe we can change "innermost" to "first".
Than, after you remove default arguments from f(), compilation fails.

Operators, which can't have default arguments anyway, are ignored,
even if called explicitly. (Is this good idea?  I'm not sure.)

What about that?

The crucial point about this idea is that default is like "smart macro"
which can be
expanded early in compilation stage, or even in preprocessing stage.
If it's going to complicate already complicated C++ semantics, I'm first to
drop the idea.

Take care,
Boris


---
[ 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: rgetov@hotmail.com (Radoslav Getov)
Date: Thu, 6 Dec 2001 18:42:32 GMT
Raw View
Pete Becker <petebecker@acm.org> wrote in message news:<3C0EB967.A8CE1A21@acm.org>...
> Boris Bralo wrote:
> >
> > Suppose you have function:
> >
> > void make_thread( thread_function* fp, void* params  =0, void* stack = 0,
> > long params = JOINABLE| NEW_LWP, thread_t* thr_id = 0 )
> >
> > and you have to your function to return you thread id . All you can do now
> > is to read header to find out what are the defaults and then write something
> > like:
> >
> > make_thread( func, 0, 0, JOINABLE| NEW_LWP, &id);
> >
> > My proposal is to introduce keyword default so you can do:
> >
> > make_thread( func, default, default, default, &id);
> >
>
> How does this work if make_thread is overloaded?
>

By finding (or failing to find)a best match, using supplied arguments' types
only? I don't see a problem here, although it will definitelly make the
rules for overloaded function selection even harder. But it's generally not
quite different than the present situation; the difference being only that
default args are not nesseccarily the 'trailing' ones.

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                ]





Author: brangdon@cix.co.uk (Dave Harris)
Date: Fri, 7 Dec 2001 17:29:32 GMT
Raw View
boris.bralo@zg.tel.hr (Boris Bralo) wrote (abridged):
> By my opinion, the most straightforward implementaition is to do
> "default" expansion as soon as is possible , somewhere early
> in processing of entity. It may be even done by preprocessor, but
> don't hold me on that, C++ preprocessor is busy enough.

It can't be done before overload resolution. Eg:

    void proc( int x, int y=INT_MAX );
    void proc( long x, long y=LONG_MAX );

    void demo() {
       // ... some code which declares 'x'.
       proc( x, default );
    }

The value for default depends on the type of x and on which overloaded
function is the best match for that type. I don't think we can tell what
it is without a full parse. That's my point, really: it's *hard* to figure
out what the code means.


> > Changing the type of the first argument changes the type injected
> > into the middle of the last expression, which is a bit unobvious.
> > (There are probably more pathological examples than I can think
> > of right now.)
>
> I don't see any problem here. Expression evaluates to [...]

I know the compiler can figure it out. I'm concerned about us poor humans.
Consider:

    double func( double );
    int func( int );

    void proc( int x, double y=1.0, int z=1 );

    void demo() {
        proc( 1, func(default), func(default) );
    }

Here the two function calls look identical, but they have totally
different meanings - they invoke different functions. The meaning of
"default" depends on context in a way unlike anything seen before in C++.

By the way, have you thought about how many times "default" is evaluated,
and whether it is an rvalue or a const? Eg:

    class Complex {
        // The usual maths stuff here.
    };
    Complex func( Complex *pComplex );

    void proc( int x, Complex y=Complex(0,0) );

    void demo() {
        proc( 0, func( &default ) );
        proc( 0, default * default.negate() + (default = Complex(1,0)) );
    }

I think the proposal is substantially simpler if we are not allowed to use
"default" in expressions.

  Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
      brangdon@cix.co.uk      |   And close your eyes with holy dread,
                              |  For he on honey dew hath fed
 http://www.bhresearch.co.uk/ |   And drunk the milk of Paradise."

---
[ 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: brangdon@cix.co.uk (Dave Harris)
Date: Fri, 7 Dec 2001 17:29:38 GMT
Raw View
rgetov@hotmail.com (Radoslav Getov) wrote (abridged):
> While I personally think that default arguments are evil and try not
> to use ones, while we are there, why not allow <empty> arguments in
> function calls? E.G. something like
>
>     make_thread( func, , , , &id);

This was proposed here a month or so ago. One problem is that it's hard to
count the commas. "Default" overcomes that problem nicely.

  Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
      brangdon@cix.co.uk      |   And close your eyes with holy dread,
                              |  For he on honey dew hath fed
 http://www.bhresearch.co.uk/ |   And drunk the milk of Paradise."

---
[ 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@web.de>
Date: Fri, 7 Dec 2001 17:32:37 GMT
Raw View
"Boris Bralo" <boris.bralo@zg.tel.hr> writes:

> Hi Pete,
> >
> > How does this work if make_thread is overloaded?
> >
> > --
> > Pete Becker
> > Dinkumware, Ltd. (http://www.dinkumware.com)
> >
> > ---
> This is a problem, but consider
>
> void abc ( int, int = 5);
> void abc ( int, double = 5.0);
>
> Then
> abc(1, default)
> is same as
> abc(1)
>
> - both calls are ambiguous.

Indeed, the explicit default could disambiguate an ambiguous call:

void foo(int, int=0);
void foo(int);

foo(3, default); // calls the first one
foo(3); // ambiguous


However, if default is allowed in argument _expressions_, you can
get new problems:

void foo(int, int=0);
void foo(int, double);

foo(5, (double)default);

Now, should the compiler choose foo(int,int=0) (because it has a
default), and implicitly re-convert (double)0 to int, or should it
choose foo(int, double) (because of the types) and give an error
because there's no default value?

---
[ 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: brangdon@cix.co.uk (Dave Harris)
Date: Fri, 7 Dec 2001 17:45:30 GMT
Raw View
richard@ex-parrot.com (Richard Smith) wrote (abridged):
> Operator functions are not allowed to have default arguments [13.5/8],
> the only exception is operator() [13.5.4/1], so this problem does
> not arise.

OK, but a similar problem arises with normal functions. The word "default"
is being injected into expressions and its not at all obvious what it
means in any given context.

  Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
      brangdon@cix.co.uk      |   And close your eyes with holy dread,
                              |  For he on honey dew hath fed
 http://www.bhresearch.co.uk/ |   And drunk the milk of Paradise."

---
[ 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: jthill_@mac.com (Jim Hill)
Date: Sat, 8 Dec 2001 01:36:45 GMT
Raw View
Christopher Eltschka <celtschk@web.de> wrote in message news:<9uqs63$4eo$1@news.tuwien.ac.at>...
> problems:
>
> void foo(int, int=0);
> void foo(int, double);
>
> foo(5, (double)default);
>
> Now, should the compiler choose foo(int,int=0) (because it has a
> default), and implicitly re-convert (double)0 to int, or should it
> choose foo(int, double) (because of the types) and give an error
> because there's no default value?

No question about it: error, because defaults are [still] applied after
overload resolution.  Your example resolves to the second foo(), exactly as
`foo(5, (double)any_convertible_rvalue);` would.

---
[ 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: Colin Rafferty <colin@xemacs.org>
Date: Tue, 4 Dec 2001 19:39:22 GMT
Raw View
Boris Bralo wrote:

> Suppose you have function:
>
> void make_thread( thread_function* fp, void* params  =0, void* stack = 0,
> long params = JOINABLE| NEW_LWP, thread_t* thr_id = 0 )
>
> and you have to your function to return you thread id . All you can
> do now is to read header to find out what are the defaults and then
> write something like:
>
> make_thread( func, 0, 0, JOINABLE| NEW_LWP, &id);
>
> My proposal is to introduce keyword default so you can do:
>
> make_thread( func, default, default, default, &id);

Your solution is fixing the wrong problem.  The real problem is that
you have too many arguments to your function.  More than three
arguments to a function is just unmanageable.  At a glance, I have no
idea what those arguments mean, since there are just too many of them.

A better idea is to have a clearer definition of make_thread().

If you have a function with five arguments, four of which are
optional, you should probably have an Argument class instead.

This would be a much clearer method:

  struct ThreadArguments
  {
    void* void_params;
    void* stack;
    long long_params;
    ThreadArguments() : params(0), stack(0), params(JOINABLE| NEW_LWP) {}
  };

  thread_t make_thread(thread_function*, const ThreadArguments&);

I can now call it like this:

  thr_id id = make_thread(func, ThreadArguments());

> Refinement can be that compiler automatically replace keyword
> default with actual value so you can do:
>
> make_thread( func, default, default, default | SCHED_FIFO);

Here is the refinement:

  ThreadArguments args;
  args.long_params |= SCHED_FIFO;
  thr_id id = make_thread(func, args);

--
Colin

---
[ 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: "Ken Alverson" <Ken@Alverson.com>
Date: Tue, 4 Dec 2001 21:26:09 GMT
Raw View
"Boris Bralo" <boris.bralo@zg.tel.hr> wrote in message
news:3c0c91a3$1@master.soko.hr...
>
> Good point. I think that logical choice would be
>
> make_thread( func, default, default, operator|(default_from_make_thread ,
> SCHED_FIFO) )
>
> but one can rightfully disagree.

I agree with the entirety of your post, the only case where I'd see a
problem is if you wanted to explicitly call operator| but still use a
default from make_thread, ie how do you express:

make_thread(func, default, default, operator|(default_from_make_thread,
default_from_operator|));

my initial feeling would be something wacky like

make_thread(func, default, default, operator|(make_thread::arg4::default,
default));

(or arg3, if you want to start at arg0, or args[3])  Now, the argument
should be able to be inferred, so that could be shortened to

make_thread(func, default, default, operator|(make_thread::default,
default));

any issues with this?  Thoughts?

Ken


---
[ 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: "Ken Alverson" <Ken@Alverson.com>
Date: Tue, 4 Dec 2001 22:31:35 GMT
Raw View
"Colin Rafferty" <colin@xemacs.org> wrote in message
news:vgv7ks2vn65.fsf@morganstanley.com...
>
> Your solution is fixing the wrong problem.  The real problem is that
> you have too many arguments to your function.  More than three
> arguments to a function is just unmanageable.  At a glance, I have no
> idea what those arguments mean, since there are just too many of them.

While I agree that default parameters are often indicative of poor interface
design, that doesn't necessarily put default parameters themselves at fault.
That said, your solution doesn't solve the case of wanting to use defaults
for template parameters...

Ken


---
[ 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: brangdon@cix.co.uk (Dave Harris)
Date: Tue, 4 Dec 2001 22:54:14 GMT
Raw View
jk@steel.orel.ru (Eugene Karpachov) wrote (abridged):
> >    enum Policy { SCHED_FIFO, ROUND_ROBIN, ... };
> >    int operator|( int=ROUND_ROBIN, Policy=ROUND_ROBIN );
> >
> >    make_thread( func, default, default, default | SCHED_FIFO);
> >
> > Does that last argument use the default of make_thread or the default
> > of operator|()?
>
> Overloading has nothing to do with it because "default | SCHED_FIFO" is
> not an expression; it's merely syntactic sugar.

I don't understand. Syntactic sugar for what? How I am supposed to decide
what "default | SCHED_FIFO" means?

It looks to me as though the name "default" is being bound to some value
within the context of the expression. You need to nail down exactly what
the scope of this binding is.

Some more examples:
    int get_flag( int base_flag );

    make_thread( func, default, default, get_flag(default) );

Since get_flag() doesn't have a default argument, do we use the default of
make_thread()? Or is this a compile-time error? I would hope the rules for
user-defined functions are consistent with those for user-defined
operators, and built-in operators.

I am still a bit bothered by the way "default" injects a type into the
middle of an expression. I suspect it will suffer from the same problems
as overloading by return type.

  Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
      brangdon@cix.co.uk      |   And close your eyes with holy dread,
                              |  For he on honey dew hath fed
 http://www.bhresearch.co.uk/ |   And drunk the milk of Paradise."

---
[ 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: jk@steel.orel.ru (Eugene Karpachov)
Date: Wed, 5 Dec 2001 16:50:33 GMT
Raw View
Tue,  4 Dec 2001 22:54:14 GMT Dave Harris wrote:
>> Overloading has nothing to do with it because "default | SCHED_FIFO" is
>> not an expression; it's merely syntactic sugar.
>
>I don't understand. Syntactic sugar for what? How I am supposed to decide
>what "default | SCHED_FIFO" means?
>
>It looks to me as though the name "default" is being bound to some value
>within the context of the expression. You need to nail down exactly what
>the scope of this binding is.

It seems I misunderstand the issue; I used to think it is a bit
"perlish": if there is default for that argument, then use the default,
else use SCHED_FIFO. I'm obviously wrong (too many perl these days :).

--
jk

---
[ 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: "Boris Bralo" <boris.bralo@zg.tel.hr>
Date: Wed, 5 Dec 2001 16:51:36 GMT
Raw View
Hi Ken,

> make_thread(func, default, default, operator|(make_thread::default,
> default));
>
> any issues with this?  Thoughts?
>
> Ken

Interesting proposal, but I must admit that is not what I meant.
I would like to make things simple, easy to implement and use.
Your proposal introduces whole new namespace between
braces of function call. My intent was to treat keyword default
like some advanced macro.

Boris


---
[ 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: "Boris Bralo" <boris.bralo@zg.tel.hr>
Date: Wed, 5 Dec 2001 16:51:45 GMT
Raw View
Hi Colin,
First, I want to emphasize that intoducing default don't force you to change
a single line of existing code.
So it won't hurt, even if it doesn't help.

> Your solution is fixing the wrong problem.  The real problem is that
> you have too many arguments to your function.  More than three
> arguments to a function is just unmanageable.  At a glance, I have no
> idea what those arguments mean, since there are just too many of them.
>
> A better idea is to have a clearer definition of make_thread().
>
> If you have a function with five arguments, four of which are
> optional, you should probably have an Argument class instead.
>
> This would be a much clearer method:
>
>   struct ThreadArguments
>   {
>     void* void_params;
>     void* stack;
>     long long_params;
>     ThreadArguments() : params(0), stack(0), params(JOINABLE| NEW_LWP) {}
>   };
>
>   thread_t make_thread(thread_function*, const ThreadArguments&);
>
> I can now call it like this:
>
>   thr_id id = make_thread(func, ThreadArguments());
>
> > Refinement can be that compiler automatically replace keyword
> > default with actual value so you can do:
> >
> > make_thread( func, default, default, default | SCHED_FIFO);
>
> Here is the refinement:
>
>   ThreadArguments args;
>   args.long_params |= SCHED_FIFO;
>   thr_id id = make_thread(func, args);
>

That's all true, but there _are_  functions with many parameters somewhere
out there.
Often, they are a part of OS API, and if you want to write realy thin
wrapper around that API,
default arguments is only thing you can do to make poor C++ programer's life
easier.
The example I used is actualy inspired by one such wrapper around thread API
(ACE communication framework). Your wrapping, although easier to use,
introduces
performance penalty

create "packing" object,
"packing" arguments ,
calling wrapper function,
    unpacking arguments,
    calling API function

against :
calling wrapper function
    calling API function

That penalty is maybe unacceptable.

Boris


---
[ 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: "Richard Smith" <richard@ex-parrot.com>
Date: Wed, 5 Dec 2001 16:51:50 GMT
Raw View
"Dave Harris" <brangdon@cix.co.uk> wrote in message
news:memo.20011203230018.57935C@brangdon.madasafish.com...
> boris.bralo@zg.tel.hr (Boris Bralo) wrote (abridged):
> > Refinement can be that compiler automatically replace keyword default
> > with actual value so you can do:
> >
> > make_thread( func, default, default, default | SCHED_FIFO);
>
> Cute. Looks a bit tricky to me. Eg:
>
>     enum Policy { SCHED_FIFO, ROUND_ROBIN, ... };
>     int operator|( int=ROUND_ROBIN, Policy=ROUND_ROBIN );

Operator functions are not allowed to have default arguments [13.5/8], the
only exception is operator() [13.5.4/1], so this problem does not arise.

--
Richard Smith


---
[ 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: "Richard Smith" <richard@ex-parrot.com>
Date: Wed, 5 Dec 2001 16:51:58 GMT
Raw View
"Ken Alverson" <Ken@Alverson.com> wrote in message
news:9ujg2t$r21$1@eeyore.INS.cwru.edu...
> "Colin Rafferty" <colin@xemacs.org> wrote in message
> news:vgv7ks2vn65.fsf@morganstanley.com...
> >
> > Your solution is fixing the wrong problem.  The real problem is that
> > you have too many arguments to your function.  More than three
> > arguments to a function is just unmanageable.  At a glance, I have no
> > idea what those arguments mean, since there are just too many of them.
>
> While I agree that default parameters are often indicative of poor
interface
> design, that doesn't necessarily put default parameters themselves at
fault.
> That said, your solution doesn't solve the case of wanting to use defaults
> for template parameters...

You can apply exactly the same idea to templates.  For example,

    template <class Key, class Type> struct hash_map_policies
    {
      typedef hash<Key>       hash_function;
      typedef equal_to<Key>   key_equal;
      typedef allocator<Type> allocator_)type;
    };

    template
    <
      class Key,
      class Type,
      template <class, class> class Policies = hash_map_policies
    >
    class my_hash_map;


And then you can use it:

    template <class Key, class Type> struct my_policies
      : hash_map_policies<Key, Type>
    {
      // Override one policy
      typedef another_allocator<Type> allocator_type;
    };

    my_map<std::string, std::vector<float>, my_policies> m;

Perhaps overkill for a class with three policies, but if it scales well as
the number of policies increases.

--
Richard Smith


---
[ 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: rgetov@hotmail.com (Radoslav Getov)
Date: Wed, 5 Dec 2001 23:21:19 GMT
Raw View
pdimov@mmltd.net (Peter Dimov) wrote in message news:<7dc3b1ea.0112030625.4e610c0@posting.google.com>...
> "Boris Bralo" <boris.bralo@zg.tel.hr> wrote in message news:<3c07b20c$1@master.soko.hr>...
> > Hi
> >
> > Suppose you have function:
> >
> > void make_thread( thread_function* fp, void* params  =0, void* stack = 0,
> > long params = JOINABLE| NEW_LWP, thread_t* thr_id = 0 )
> >
> > and you have to your function to return you thread id . All you can do now
> > is to read header to find out what are the defaults and then write something
> > like:
> >
> > make_thread( func, 0, 0, JOINABLE| NEW_LWP, &id);
> >
> > My proposal is to introduce keyword default so you can do:
> >
> > make_thread( func, default, default, default, &id);
>
> I can't see any counter arguments to this proposal. None. Zero. It
> doesn't even require a new keyword.
>
> --
> Peter Dimov
> Multi Media Ltd.
>

While I personally think that default arguments are evil and try not
to use ones, while we are there, why not allow <empty> arguments in
function calls? E.G. something like

    make_thread( func, , , , &id);

IMO it's somewhat more consistent with what the default args are
(i.e. something present but omitted and therefore using a default value).

Might be the proposal using a keyword will be easier to parse, but
I doubt that one would be so difficult either.


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                ]





Author: Adam Peterson <ahp6@email.byu.edu>
Date: Wed, 5 Dec 2001 23:22:20 GMT
Raw View
"Boris Bralo" <boris.bralo@zg.tel.hr> wrote in message
news:3c0c91a3$1@master.soko.hr...
> Hi Dave,
>
> > Cute. Looks a bit tricky to me. Eg:
> >
> >     enum Policy { SCHED_FIFO, ROUND_ROBIN, ... };
> >     int operator|( int=ROUND_ROBIN, Policy=ROUND_ROBIN );
> >
> >     make_thread( func, default, default, default | SCHED_FIFO);
> >
> > Does that last argument use the default of make_thread or the default of
> > operator|()? What about if we wrote it:
>
> Good point. I think that logical choice would be
>
> make_thread( func, default, default, operator|(default_from_make_thread ,
> SCHED_FIFO) )
>
> but one can rightfully disagree.
>
> By my opinion, the most straightforward implementaition is to do
"default"
> expansion as soon as is possible , somewhere early in processing of
entity.
> It may be even done by preprocessor, but don't hold me on that, C++
> preprocessor is busy enough.
> The formal specification could be :
>
> default expands to the default argument of  the EXPLICIT innermost scope.
>
> so in
> make_thread( func, default, default, operator|(default,SCHED_FIFO) );
>
> default expands to the default of operator|() , because operator|() is
> _explicitly_ invoked.
>
> and in
> test<>( 1, 0, 12 * (42 - default) );
>
>
> default expands to the default of test()  regardless of existance of
> operator-(int,  T = T()).
> To use default from operator-() one must write:
> test<>( 1, 0, 12 * operator-(42, default) );

I strongly object to any proposal that introduces significant differences
between the two forms of calling an operator function.  I often call
operator functions explicitly within my classes.

I also think that the binding of default to innermost valid function needs
to be rethought.

Imagine:


void f(int, int=1);
void g(int=2);
int main() {
    g(f(1, default+1));
}


Now, someone changes
    void f(int, int=1);
to
    void f(int, int);
    void f(int);

Suddenly, code changes meaning silently.  default is now bound to g's
default, instead of f's.


---
[ 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: Colin Rafferty <colin@xemacs.org>
Date: Wed, 5 Dec 2001 23:22:05 GMT
Raw View
Boris Bralo wrote:

> First, I want to emphasize that intoducing default don't
> force you to change a single line of existing code.

I agree that it is a pure extension, and that it does not effect
existing code.

> So it won't hurt, even if it doesn't help.

I disagree.  It will assist people in making the bad design decision
of having a tremendous number of arguments to a function.

> Colin Rafferty writes:

>> Your solution is fixing the wrong problem.  The real problem is
>> that you have too many arguments to your function.

> That's all true, but there _are_ functions with many parameters
> somewhere out there.  Often, they are a part of OS API, and if you
> want to write realy thin wrapper around that API, default arguments
> is only thing you can do to make poor C++ programer's life easier.

Writing thin wrappers is generally a bad idea.  Rather than writing a
thin wrapper, just calling the functions directly is the most
straightforward way to handle things.

This is not to say that writing wrappers is a bad idea.  But thin
wrappers are just ways of renaming functions, but not actually
changing anything.

> The example I used is actualy inspired by one such wrapper around
> thread API (ACE communication framework). Your wrapping, although
> easier to use, introduces performance penalty.

It is possible that my wrapper introduces a performance penalty.  On
the other hand, I worry more about how easy it is to write and
maintain a program, and when I'm done, I profile it to see where the
actual performance problems are.  Only when I've done that will I
start making those specific problem areas more difficult to maintain.

--
Colin

---
[ 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: Pete Becker <petebecker@acm.org>
Date: Thu, 6 Dec 2001 00:19:37 GMT
Raw View
Boris Bralo wrote:
>
> Suppose you have function:
>
> void make_thread( thread_function* fp, void* params  =0, void* stack = 0,
> long params = JOINABLE| NEW_LWP, thread_t* thr_id = 0 )
>
> and you have to your function to return you thread id . All you can do now
> is to read header to find out what are the defaults and then write something
> like:
>
> make_thread( func, 0, 0, JOINABLE| NEW_LWP, &id);
>
> My proposal is to introduce keyword default so you can do:
>
> make_thread( func, default, default, default, &id);
>

How does this work if make_thread is overloaded?

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





Author: jthill_@mac.com (Jim Hill)
Date: Thu, 6 Dec 2001 18:16:58 GMT
Raw View
Colin Rafferty <colin@xemacs.org> wrote in message news:<vgvbshdtmo1.fsf@morganstanley.com>...
> Only when I've done that will I
> start making those specific problem areas more difficult to maintain.

Granted, long parameter lists and default arguments are a very
slippery slope.

Still:  more difficult than what? for whom?

This proposal, as I see it, isn't for native C++ code but for C
migration. For that use I'm with Peter Dimov: it's all good.  It
immediately makes the life of C coders used to the original API
easier, with changes that are unobtrusive in the source.

And I don't buy the ~silent changes~ problem: `T f(T,T=0);` to `T
f(T,T);T f(T);` is just as easily an argument _for_ `default`:
T(1,default) would then generate an error, where T(1) would call an
entirely different function.  One can't object that nobody would do
that (i.e. any of the several opportunities for dumb-itude there) --
this entire line of argument is about people doing dumb things.  Wanna
predict which dumb thing anybody's going to choose?

And further, not everyone is immediately willing to spend time finding
advantages to new ways of doing things -- that's why C++ was based on
C, after all.  I think there's a lot to be said for making C++ a
better C, too.

In an argument expression, `default` is identical to the
[parenthesized] default expression for its parameter in the same way
`a[i]` is identical to `(*(a+i))`.  I'll probably never use it, but it
gets my vote.

---
[ 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: "Boris Bralo" <boris.bralo@zg.tel.hr>
Date: Thu, 6 Dec 2001 18:35:55 GMT
Raw View
Hi Pete,
>
> How does this work if make_thread is overloaded?
>
> --
> Pete Becker
> Dinkumware, Ltd. (http://www.dinkumware.com)
>
> ---
This is a problem, but consider

void abc ( int, int = 5);
void abc ( int, double = 5.0);

Then
abc(1, default)
is same as
abc(1)

- both calls are ambiguous.

Boris


---
[ 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: pdimov@mmltd.net (Peter Dimov)
Date: Mon, 3 Dec 2001 18:46:06 GMT
Raw View
"Boris Bralo" <boris.bralo@zg.tel.hr> wrote in message news:<3c07b20c$1@master.soko.hr>...
> Hi
>
> Suppose you have function:
>
> void make_thread( thread_function* fp, void* params  =0, void* stack = 0,
> long params = JOINABLE| NEW_LWP, thread_t* thr_id = 0 )
>
> and you have to your function to return you thread id . All you can do now
> is to read header to find out what are the defaults and then write something
> like:
>
> make_thread( func, 0, 0, JOINABLE| NEW_LWP, &id);
>
> My proposal is to introduce keyword default so you can do:
>
> make_thread( func, default, default, default, &id);

I can't see any counter arguments to this proposal. None. Zero. It
doesn't even require a new keyword.

--
Peter Dimov
Multi Media Ltd.

---
[ 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: brangdon@cix.co.uk (Dave Harris)
Date: Mon, 3 Dec 2001 23:14:29 GMT
Raw View
boris.bralo@zg.tel.hr (Boris Bralo) wrote (abridged):
> Refinement can be that compiler automatically replace keyword default
> with actual value so you can do:
>
> make_thread( func, default, default, default | SCHED_FIFO);

Cute. Looks a bit tricky to me. Eg:

    enum Policy { SCHED_FIFO, ROUND_ROBIN, ... };
    int operator|( int=ROUND_ROBIN, Policy=ROUND_ROBIN );

    make_thread( func, default, default, default | SCHED_FIFO);

Does that last argument use the default of make_thread or the default of
operator|()? What about if we wrote it:

    make_thread( func, default, default, operator|(default,SCHED_FIFO) );

I am also concerned about how it interacts with overloading and templates.
I don't think the compiler can get confused - no new ambiguities - but it
might be disconcerting for humans.

    template <typename T>
    void test( T t, int x, T t3=0 );

    test( 1, 0, 12 * (42 - default) );

Changing the type of the first argument changes the type injected into the
middle of the last expression, which is a bit unobvious. (There are
probably more pathological examples than I can think of right now.)

  Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
      brangdon@cix.co.uk      |   And close your eyes with holy dread,
                              |  For he on honey dew hath fed
 http://www.bhresearch.co.uk/ |   And drunk the milk of Paradise."

---
[ 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: jk@steel.orel.ru (Eugene Karpachov)
Date: Tue, 4 Dec 2001 18:34:02 GMT
Raw View
Mon,  3 Dec 2001 23:14:29 GMT Dave Harris wrote:
>    enum Policy { SCHED_FIFO, ROUND_ROBIN, ... };
>    int operator|( int=ROUND_ROBIN, Policy=ROUND_ROBIN );
>
>    make_thread( func, default, default, default | SCHED_FIFO);
>
>Does that last argument use the default of make_thread or the default of
>operator|()?

Overloading has nothing to do with it because "default | SCHED_FIFO" is
not an expression; it's merely syntactic sugar.

--
jk

---
[ 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: "Boris Bralo" <boris.bralo@zg.tel.hr>
Date: Tue, 4 Dec 2001 19:36:24 GMT
Raw View
Hi Dave,

> Cute. Looks a bit tricky to me. Eg:
>
>     enum Policy { SCHED_FIFO, ROUND_ROBIN, ... };
>     int operator|( int=ROUND_ROBIN, Policy=ROUND_ROBIN );
>
>     make_thread( func, default, default, default | SCHED_FIFO);
>
> Does that last argument use the default of make_thread or the default of
> operator|()? What about if we wrote it:

Good point. I think that logical choice would be

make_thread( func, default, default, operator|(default_from_make_thread ,
SCHED_FIFO) )

but one can rightfully disagree.

By my opinion, the most straightforward implementaition is to do  "default"
expansion as soon as is possible , somewhere early in processing of entity.
It may be even done by preprocessor, but don't hold me on that, C++
preprocessor is busy enough.
The formal specification could be :

default expands to the default argument of  the EXPLICIT innermost scope.

so in
make_thread( func, default, default, operator|(default,SCHED_FIFO) );

default expands to the default of operator|() , because operator|() is
_explicitly_ invoked.

and in
test<>( 1, 0, 12 * (42 - default) );


default expands to the default of test()  regardless of existance of
operator-(int,  T = T()).
To use default from operator-() one must write:
test<>( 1, 0, 12 * operator-(42, default) );

That way declarative nature of keyword is emphasized i.e. compiler won't do
anything behind our back.
>
> I am also concerned about how it interacts with overloading and templates.
> I don't think the compiler can get confused - no new ambiguities - but it
> might be disconcerting for humans.
>
>     template <typename T>
>     void test( T t, int x, T t3=0 );
>
>     test( 1, 0, 12 * (42 - default) );
>
> Changing the type of the first argument changes the type injected into the
> middle of the last expression, which is a bit unobvious. (There are
> probably more pathological examples than I can think of right now.)

I don't see any problem here. Expression evaluates to

test<T>( t , 0, operator*( 12, operator-(42,
default_argument_of_test_or_acceptable_conversion) ) );

As far as exists unambiguous acceptable conversion from T to the second
argument of operator-()
the expression compiles and is unambiguous - exactly the same requirements
as for:

test<T>( t , 0, 12* (42 - T()));

Boris


---
[ 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: "Boris Bralo" <boris.bralo@zg.tel.hr>
Date: Fri, 30 Nov 2001 19:28:27 GMT
Raw View
Hi

Suppose you have function:

void make_thread( thread_function* fp, void* params  =0, void* stack = 0,
long params = JOINABLE| NEW_LWP, thread_t* thr_id = 0 )

and you have to your function to return you thread id . All you can do now
is to read header to find out what are the defaults and then write something
like:

make_thread( func, 0, 0, JOINABLE| NEW_LWP, &id);

My proposal is to introduce keyword default so you can do:

make_thread( func, default, default, default, &id);

The benefit is:
- not hard to implement
- when make_thread's author changes defaults the change is propagated to
user code
- declarative- intent "I'll go with defaults, whatever they might be" is
clearly shown

Refinement can be that compiler automatically replace keyword default with
actual value so
you can do:

make_thread( func, default, default, default | SCHED_FIFO);

Compiler generates the default parameters anyway.


The same apply for default template parameters. I think that, because of
different context,
we can even reuse the same keyword, but don't hold me on that

template <typename T, typename A = std::allocator<T>, typename Threading =
SingleThreadingPolicy>
class Container
{
....
}

so, if you want to specify multithreading policy instead of :

Container<double, std::allocator<double>, MultiThreadingPolicy>

you write

Container<double, default, MultiThreadingPolicy>


Later, if you find ultra-super-fast allocator template and want it to be
your default,
the changes are automagically propagated to every code that'll go with
defaults.


Any thoughts?

Boris


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