On 07/06/16 14:45, Rick C. Hodgin wrote:
> On Monday, June 6, 2016 at 9:42:06 AM UTC-4, Alf P. Steinbach wrote:
>> On 06.06.2016 14:53, Rick C. Hodgin wrote:
>>> I was trying to do this today, and it's not allowed in Microsoft's C++
>>> compiler:
>>>
>>> // In header file
>>> int myfunc(int val1, int val2 = val1);
>>>
>>> // In source file
>>> int myfunc(int val1, int val2)
>>> {
>>> // Code goes here
>>> }
>>>
>>> Is it allowed?
>>
>> Nope.
>>
What would be the use-cases of such a default parameter? I could think
of a few occasions, but none that would be common enough to make it
worth adding to the standard. And rather having the default of "val2"
being simply the same as "val1", I think there would be more useful
cases for the default of "val2" being an expression in "val1". But that
would quickly get difficult to specify well - and I think Bo Persson's
neat workaround makes complicated defaults unnecessary. Rather than
writing:
void sendString(const char* p, int len = strlen(p));
you just write:
void sendString(const char* p, int len);
inline void sendString(const char* p) {
sendString(p, strlen(p);
}
>>
>> Worse, in my opinion: in a class you can't do e.g.
>>
>> struct S
>> {
>> int x;
>> void foo( int t = x ) {} //! Nyet.
>> };
>>
That could be neat. But again, it can be handled by the easy workaround.
On the other hand, given that there /is/ an easy workaround, then it
should not be too difficult to implement the syntax you want.
>
> It's all good. :-)
>
> Personally, I think it's a missing feature, and I'm surprised someone of
> influence in the C++ standards group hasn't already wanted this ability
> by now. But, as Bo Persson points out, an easy work-around. That's
> probably why.
>
> I think this is also a missing feature:
>
> // In header
> int myfunc(int a, int b = local_b);
>
> // In body
> int myfunc(int a, int b)
> {
> return(a + b);
> }
>
> // Where referenced in source code
> int elsewhere(void)
> {
> int local_b = 5;
>
> return(myfunc(1));
> }
>
> I think the ability should exist for parameter defaults to be able to
> reference things that are in scope locally or globally.
>
This would make the header file depend on variables declared in the
source file that uses the header - that's going to open a /huge/ can of
worms.
In C++, you can currently write:
#include <functional>
using std::bind;
using namespace std::placeholders;
int elsewhere(void) {
int local_b = 5;
auto org_myfunc = myfunc;
auto myfunc = bind(org_myfunc, _1, local_b);
return myfunc(1);
}
or, using lambdas,
int elsewhere(void) {
int local_b = 5;
auto org_myfunc = myfunc;
auto myfunc = [local_b, org_myfunc](int a)
{ return org_myfunc(a, local_b); };
return myfunc(1);
}
or, using classes,
class Fmyfunc {
private :
int def_b;
public :
Fmyfunc(int default_b = 0) : def_b(default_b) {};
int operator()(int a, int b) { return myfunc(a, b); };
int operator()(int a) { return (*this)(a, def_b); };
void setDefault(int default_b = 0) { def_b = default_b; };
};
int elsewhere(void) {
int local_b = 5;
auto myfunc = Fmyfunc(local_b);
return myfunc(1);
}
You can also use templates in creative ways here.
(In each of these cases, gcc has no problem generating optimal code, so
there is no run-time overhead.)
In other words, you can make your own local version of "myfunc" which
has local modifications (such as a different default). This puts the
control of the local modifications where it should be, where it is used
- and leaves the definition and implementation of myfunc unaware of the
local modifications.
The challenge for your language is to come up with a neater syntax for
doing this! An obvious improvement would be to allow:
auto myfunc = bind(myfunc, _1, local_b);
instead of
auto org_myfunc = myfunc;
auto myfunc = bind(org_myfunc, _1, local_b);
A key point here is to allow functions to be manipulated directly, or
nearly directly - if functions are first-class objects, all sorts of
tricks are possible.