Default values in middle parameters in a function

451 views
Skip to first unread message

Hariharan Subramanian

unread,
Apr 29, 2013, 6:15:28 AM4/29/13
to std-pr...@isocpp.org
Problem:
Change the default value of a default parameter in a function might result in a surprising behaviour. The problem is described below.
Consider the following function declaration & definition

//file1.h
void foo(int param, type1 value1 = a1, type2 value2 = b1);

//file1.cpp
#include "file.h"
void foo(int param, type1 value1, type2 value2) {
        //implementation
}

//file2.cpp
#include "file1.h"

void usefoo() {
       foo(0, a1, b2); //i want to pass b2 and hence i am passing the default value a1 also
}

It is often the case that during the lifecycle of the software the default value is changed to a2 from a1. This necessitates a change in the function usefoo(). As there is no compilation error it is very easy to miss this error. Even if the person knows that it should be changed it is a cumbersome manual process (change it in all the places) and hence error prone. This kind of change is not uncommon at all. Days of work gets wasted due to this.

Solution:
Introduce the default keyword during the function call. The function call becomes

void usefoo() {
       foo(0, default, b2);
}

Now, no matter what the change in the default value the usefoo function will not produce any surprise. It might seem that the mirror image of the problem exists. If a user wants to pass a1 then changing the default value to a2 will result in a problem. The problem can be solved like this below.

foo(0, default, b2); // if the user wants to pass whatever the default value is
foo(0, a1, b2);       // if the user wants to pass a1 no matter what the default value is

Addition of this functionality matches the user intent.

Lawrence Crowl

unread,
Apr 29, 2013, 3:03:15 PM4/29/13
to std-pr...@isocpp.org
Default parameters can vary between translation units, which is
not good for code clarity. They can also cause address-of-function
problems and binary compatibility problems. An overload set is a
significantly better approach to the problems that default parameters
solve. I would rather the user wrote function overloads to handle
the various cases. Mostly, you can do this in an API-compatible
manner. So, rather than extend a flawed feature, I would rather say
"do not do that".

--
Lawrence Crowl

Hariharan Subramanian

unread,
Apr 30, 2013, 1:32:40 AM4/30/13
to std-pr...@isocpp.org
Default parameters can vary between translation units, which is
not good for code clarity.  They can also cause address-of-function
problems and binary compatibility problems.  An overload set is a
significantly better approach to the problems that default parameters
solve.  I would rather the user wrote function overloads to handle
the various cases.  Mostly, you can do this in an API-compatible
manner.  So, rather than extend a flawed feature, I would rather say
"do not do that".

Default parameters are a reality and used extensively. Instead of making a "flawed feature" difficult to work with it makes this "flawed feature" easier to work with. 

Nicol Bolas

unread,
Apr 30, 2013, 2:43:50 AM4/30/13
to std-pr...@isocpp.org

Personally, I don't think that default parameters are a "flawed feature". That being said, the flaws discussed are not resolved by your suggestion.

Default parameters solve a simple, very specific problem. Function overloading solves a larger, more general problem. I like that we have both. And I think that the problem that you intend to solve, with some kind of "default" parameter, is best solved with the larger, more general solution.

Also, with `optional`:

void foo(int param, optional<type1> value1, optional<type2> value2) {
  type1 val1
= value1.value_or(a1);
  type2 val2
= value2.value_or(a2);
 
//implementation
}

void usefoo() {
       foo
(0, nullopt, b2);
}

That seems to take care of the problem.

Hariharan Subramanian

unread,
Apr 30, 2013, 3:57:07 AM4/30/13
to std-pr...@isocpp.org

Personally, I don't think that default parameters are a "flawed feature". That being said, the flaws discussed are not resolved by your suggestion.

Default parameters solve a simple, very specific problem. Function overloading solves a larger, more general problem. I like that we have both. And I think that the problem that you intend to solve, with some kind of "default" parameter, is best solved with the larger, more general solution.

Also, with `optional`:

void foo(int param, optional<type1> value1, optional<type2> value2) {
  type1 val1
= value1.value_or(a1);
  type2 val2
= value2.value_or(a2);
 
//implementation
}

void usefoo() {
       foo
(0, nullopt, b2);
}

That seems to take care of the problem.


This does not work.

//foo.h
void foo(int a, type1 param1, type2 param2 = value2);

//foo.cpp
void foo(int a, type1 param1, type2 param2) {
   //Is param1 value1 or value3?
}

//usefoo1.cpp
void foo(int a, type1 param1 = value1, type2 param2);
void usefoo1() {
     foo(1);
}

//usefoo2.cpp
void foo(int a, type1 param1 = value3, type2 param2);
void usefoo2() {
     foo(1);
}

From the above example it is clear that the caller decides the default values with the function based on the latest declaration that is available to it. So foo() cannot decide the default values.

Regarding the Lawrence' comment that default parameters being unnecessary: We need to define as many overloaded functions as the number of default parameters. Besides it will be hidden in the source and will not be available if only the headers are available.

Nicol Bolas

unread,
Apr 30, 2013, 5:41:40 AM4/30/13
to std-pr...@isocpp.org

Yes, that doesn't work. I agree. And it should never work.

Re-declaring functions with different default parameters is a horrible idea. Default parameters should be considered part of a function's interface.

What you're trying to do is a wrong thing. Default parameters are a tool for the person implementing the function, not for person calling it. If you want to have some helper function in a source file that uses other defaults that are local to that source file, the declare a helper function that fills in the default for you:

//foo.h
void foo(int a, type1 param1, type2 param2 = value2);
//foo.cpp
void foo(int a, type1 param1, type2 param2) {
   
//Is param1 value1 or value3?
}
//usefoo1.cpp
static void usefoo1() {
     foo
(1, value1);
}
//usefoo2.cpp
static void usefoo2() {
     foo
(1, value3);
}

See? That wasn't hard. Your default parameters are there, and any compiler worth using will likely inline them for you.

The C++ committee ought not add features to support this usage pattern for default parameters.

Hariharan Subramanian

unread,
Apr 30, 2013, 7:06:45 AM4/30/13
to std-pr...@isocpp.org
Yes, that doesn't work. I agree. And it should never work.

Re-declaring functions with different default parameters is a horrible idea. Default parameters should be considered part of a function's interface.

I personally do not like to re-declare functions like that. But it's the choice of the individual. 
 
What you're trying to do is a wrong thing. Default parameters are a tool for the person implementing the function, not for person calling it. If you want to have some helper function in a source file that uses other defaults that are local to that source file, the declare a helper function that fills in the default for you:

I just pointed out that solution proposed in your previous email does not work in that case. There are lot of existing APIs which do not follow your solution and they will be difficult to use. Whereas using default middle parameter makes it easy to use.
 

//foo.h
void foo(int a, type1 param1, type2 param2 = value2);
//foo.cpp
void foo(int a, type1 param1, type2 param2) {
   
//Is param1 value1 or value3?
}
//usefoo1.cpp
static void usefoo1() {
     foo
(1, value1);
}
//usefoo2.cpp
static void usefoo2() {
     foo
(1, value3);
}

See? That wasn't hard. Your default parameters are there, and any compiler worth using will likely inline them for you.

The C++ committee ought not add features to support this usage pattern for default parameters.

Default middle parameter proposal neither encourages nor discourages such usage pattern. If such a pattern should not be supported then that should be deprecated and removed subsequently instead of allowing the users to do it and also making it difficult to do it. The use case for this proposal is not this re-declaration case. It is just that it makes it easy to use that function.
void foo(int a, type1 param1 = value1, type2 param2 = value2);
Assume that 50% of the users set param1 to value3 and want default value for param2 and the rest set param2 to value4 and want default value for param1. Because of the order of the declaration of parameters only 50% of the users will find it easier to use. The other 50% will not find it easier to use. It makes it easy for all to use. Any change in the default value will be automatically taken care of. Otherwise such a change forces a change everywhere which is cumbersome and error prone.

Regards,
Hariharan S

Vincent Jacquet

unread,
Apr 30, 2013, 8:10:46 AM4/30/13
to std-pr...@isocpp.org
I don't agree that default parameters are a tool for the person implementing the function. They are a tool for the person calling it. You could add default parameters to a function without changing a line of its implementation. It does not make the implementation easier (other than ensuring that the parameter is always defined), it makes the calling more convenient.

This also why I do not like the idea of using optional in place of default parameters. With optional, you hide the default value and you resolve it at runtime instead of compile time. You could change the value used as default and I would never know. By doing so, you might even break my code.
Providing several overrides also hides the default parameters value, so it is almost the same but without the runtime penalty.

Best regards,
Vincent

Nicol Bolas

unread,
Apr 30, 2013, 8:31:03 AM4/30/13
to std-pr...@isocpp.org
On Tuesday, April 30, 2013 4:06:45 AM UTC-7, Hariharan Subramanian wrote:

Yes, that doesn't work. I agree. And it should never work.

Re-declaring functions with different default parameters is a horrible idea. Default parameters should be considered part of a function's interface.

I personally do not like to re-declare functions like that. But it's the choice of the individual.

It's only a "choice of the individual" because of the limitations of the C++ language. It was never the intent of the language to allow users to arbitrarily re-declare default parameters like that. It is simply an outgrowth of what is possible, as necessitated by the way the language works.

To make default parameters operate as efficiently as non-default parameters, it was necessary for them to be something that is part of the function declaration. That way, the compilation of the calling source code would fill in the extra parameters, rather than some centralized code. Coupled with the fact that the function definition is not linked to these default parameters (it's not a part of the function's type), it becomes possible to re-declare functions with different default parameters.

This was not what was intended. It's merely an outgrowth, an accident.

It should not be supported or encouraged.

//foo.h
void foo(int a, type1 param1, type2 param2 = value2);
//foo.cpp
void foo(int a, type1 param1, type2 param2) {
   
//Is param1 value1 or value3?
}
//usefoo1.cpp
static void usefoo1() {
     foo
(1, value1);
}
//usefoo2.cpp
static void usefoo2() {
     foo
(1, value3);
}

See? That wasn't hard. Your default parameters are there, and any compiler worth using will likely inline them for you.

The C++ committee ought not add features to support this usage pattern for default parameters.

Default middle parameter proposal neither encourages nor discourages such usage pattern. If such a pattern should not be supported then that should be deprecated and removed subsequently instead of allowing the users to do it and also making it difficult to do it. The use case for this proposal is not this re-declaration case. It is just that it makes it easy to use that function.

But the re-declaration case is exactly what makes the optional method not work. If you remove the silly re-declaration stuff, then the optional method would work perfectly fine.

So if your use case is not about re-declaration, then why is it that `optional` won't solve the problem?

(FYI: the correct answer to the question I just asked is, "what do you do about reference parameters, like `const T&`?")
 
void foo(int a, type1 param1 = value1, type2 param2 = value2);
Assume that 50% of the users set param1 to value3 and want default value for param2 and the rest set param2 to value4 and want default value for param1. Because of the order of the declaration of parameters only 50% of the users will find it easier to use.

Or they can just use `foo(val, nullopt, value4);` with the previously discussed `optional` method. See? It's the re-declaration that made the optional method fail.

Hariharan Subramanian

unread,
Apr 30, 2013, 9:18:32 AM4/30/13
to std-pr...@isocpp.org
It's only a "choice of the individual" because of the limitations of the C++ language. It was never the intent of the language to allow users to arbitrarily re-declare default parameters like that. It is simply an outgrowth of what is possible, as necessitated by the way the language works.

It is neither an accident nor an outgrowth. It was a well intended move. Otherwise they could have avoided the re-declaration by making it a compiler error.

void foo(int, type1 param1, type2 param2 = value2); //original declaration
void foo(int, type1 param1 = value1, type2 param2); //re-declaration

It can be seen that the re-declaration adds a default value for param1 and for param2 it does nothing. This is certainly not an accident. It was intentional. 
 
To make default parameters operate as efficiently as non-default parameters, it was necessary for them to be something that is part of the function declaration. That way, the compilation of the calling source code would fill in the extra parameters, rather than some centralized code. Coupled with the fact that the function definition is not linked to these default parameters (it's not a part of the function's type), it becomes possible to re-declare functions with different default parameters.

This was not what was intended. It's merely an outgrowth, an accident.

It should not be supported or encouraged.

If a feature is not deprecated i don't see any point in not using it.
 

But the re-declaration case is exactly what makes the optional method not work. If you remove the silly re-declaration stuff, then the optional method would work perfectly fine.

So if your use case is not about re-declaration, then why is it that `optional` won't solve the problem?

(FYI: the correct answer to the question I just asked is, "what do you do about reference parameters, like `const T&`?")
 
 
The motivation for me to propose is the use case which I mentioned. It so happens that it works for re-declaration stuff properly. Whereas nullopt does not work for re-declaration.

Or they can just use `foo(val, nullopt, value4);` with the previously discussed `optional` method. See? It's the re-declaration that made the optional method fail.

Re-declaration is a valid feature and it is not deprecated. Hence it can be a reason for default middle parameter scoring over nullopt. Moreover, nullopt does not work for existing APIs. This is another reason.

Regards,
Hariharan S

Lawrence Crowl

unread,
Apr 30, 2013, 1:40:26 PM4/30/13
to std-pr...@isocpp.org
On 4/30/13, Hariharan Subramanian <toh...@gmail.com> wrote:
> The motivation for me to propose is the use case which I
> mentioned. It so happens that it works for re-declaration stuff
> properly. Whereas nullopt does not work for re-declaration.

Would named arguments meet your need? E.g.

int foo( type1 arg1=value1, type2 arg2=value2, type3 arg3=value3);

And to use a syntax that I am pretty sure will not work,
foo(arg3 is value4) means foo(value1, value2, value4).

--
Lawrence Crowl

Hariharan Subramanian

unread,
Apr 30, 2013, 3:08:33 PM4/30/13
to std-pr...@isocpp.org
Named arguments is too powerful a tool for this purpose. It might solve a bigger problem. For this smaller problem a simple default suffices.

Regards,
Hariharan S

Vicente J. Botet Escriba

unread,
Apr 30, 2013, 6:05:44 PM4/30/13
to std-pr...@isocpp.org
Le 29/04/13 12:15, Hariharan Subramanian a �crit :
This should also work

// header
namespace detail {
foo_value1_default() {return a1};
}
void foo(int param, type1 value1 = foo_value1_default(), type2 value2 =
b1);
void foo(int param, type2 value2 = b1) {foo(param,
foo_value1_default(), value2);}

//usage
foo(0);
foo(0, b1);
foo(0, b1, b2);
foo(0, b2);

It requires minor gymnastic for the implementer, but from the user point
of view it provides what you where locking for.

Best,
Vicente

Hariharan Subramanian

unread,
Apr 30, 2013, 11:14:17 PM4/30/13
to std-pr...@isocpp.org
If my understanding of your solution is correct, the number of functions an implementer has to write is exponential in the size of the number of default parameters. I think it's a subset problem.

Regards,
Hariharan S


On Wed, May 1, 2013 at 3:35 AM, Vicente J. Botet Escriba <vicent...@wanadoo.fr> wrote:
Le 29/04/13 12:15, Hariharan Subramanian a écrit :


--

--- You received this message because you are subscribed to a topic in the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this topic, visit https://groups.google.com/a/isocpp.org/d/topic/std-proposals/4tWQEMqEH8s/unsubscribe?hl=en.
To unsubscribe from this group and all its topics, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/?hl=en.



Vicente J. Botet Escriba

unread,
May 1, 2013, 4:00:22 AM5/1/13
to std-pr...@isocpp.org
On Wed, May 1, 2013 at 3:35 AM, Vicente J. Botet Escriba <vicent...@wanadoo.fr> wrote:
Le 29/04/13 12:15, Hariharan Subramanian a écrit :
Solution:
Introduce the default keyword during the function call. The function call becomes

void usefoo() {
       foo(0, default, b2);
}
This should also work

// header
namespace detail {
  foo_value1_default() {return a1};
}
void foo(int param, type1 value1 = foo_value1_default(), type2 value2 = b1);
void foo(int param,  type2 value2 = b1) {foo(param, foo_value1_default(), value2);}

//usage
       foo(0);
       foo(0, b1);
       foo(0, b1, b2);
       foo(0, b2);

It requires minor gymnastic for the implementer, but from the user point of view it provides what you where locking for.



Le 01/05/13 05:14, Hariharan Subramanian a écrit :
If my understanding of your solution is correct, the number of functions an implementer has to write is exponential in the size of the number of default parameters. I think it's a subset problem.


You are right, if the number of defaulted parameters is big, but I would not try to solve this problem changing the language.

The alternative to avoid all the overload that is close to your default would be for the user to use the foo_value1_default.

       foo(0, foo_value1_default(), b2);

This is less elegant, but do you really think that it is worth changing the language to improve it?

If named parameters were there would you request this feature?

Vicente

Hariharan Subramanian

unread,
May 1, 2013, 4:50:13 AM5/1/13
to std-pr...@isocpp.org

You are right, if the number of defaulted parameters is big, but I would not try to solve this problem changing the language.

The alternative to avoid all the overload that is close to your default would be for the user to use the foo_value1_default.

       foo(0, foo_value1_default(), b2);

This is less elegant, but do you really think that it is worth changing the language to improve it?


 I don't think it solves this problem.
1. If foo_value1_default() is to be written by the user of foo then he has to change it every time the creator of foo changes the default value. This suffers from the same problem which it tries to solve. (No need to check the default value. Just pass it automatically)
2. If foo_value1_default() is to be written by the creator of foo then it will not work for the existing functions. For newer functions the writer of foo has to ensure a few things.
a) definition of foo_value1_default() should be in the header file (because it is a problem if the source code is not available and only the header is available).
b) both the creator of foo and the user of foo must check that the value returned by foo_value1_default() matches with the one in the function declaration. This again suffers from the same problem which it tries to solve. (No need to check the default value. Just pass it automatically)

If named parameters were there would you request this feature?

Named parameters solves this problem. But introducing named parameters only for this would be an overkill. Even otherwise, I think named parameters is unnecessary. Cannot the IDE simply display the name of the parameter adjacent to the parameter passed? No need to change the language at all. Named parameters would have been useful during the 1990s but not now.

Regards,
Hariharan S

temp...@freemail.hu

unread,
May 1, 2013, 5:03:18 AM5/1/13
to std-pr...@isocpp.org
I think it's an excellent idea. Simple and obvious. Which means that its chances of being accepted in this forum are very slim, I'm afraid!

Hariharan Subramanian

unread,
May 1, 2013, 8:47:03 AM5/1/13
to std-pr...@isocpp.org
Thanks for the heads up :).

Regards,
Hariharan S


On Wed, May 1, 2013 at 2:33 PM, <temp...@freemail.hu> wrote:
I think it's an excellent idea. Simple and obvious. Which means that its chances of being accepted in this forum are very slim, I'm afraid!

--
 
---
You received this message because you are subscribed to a topic in the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this topic, visit https://groups.google.com/a/isocpp.org/d/topic/std-proposals/4tWQEMqEH8s/unsubscribe?hl=en.
To unsubscribe from this group and all its topics, send an email to std-proposal...@isocpp.org.

Lawrence Crowl

unread,
May 1, 2013, 1:44:52 PM5/1/13
to std-pr...@isocpp.org
On 4/30/13, Hariharan Subramanian <toh...@gmail.com> wrote:
One of the tasks of the committee is to balance the value of
new features against the increasing complexity of the language.
Whenever we can serve several different needs with one language
feature, we save everyone considerable effort to learn things.

--
Lawrence Crowl

Tony V E

unread,
May 1, 2013, 4:41:04 PM5/1/13
to std-pr...@isocpp.org
On Wed, May 1, 2013 at 4:50 AM, Hariharan Subramanian <toh...@gmail.com> wrote:

Named parameters solves this problem. But introducing named parameters only for this would be an overkill. Even otherwise, I think named parameters is unnecessary. Cannot the IDE simply display the name of the parameter adjacent to the parameter passed? No need to change the language at all. Named parameters would have been useful during the 1990s but not now.

Regards,
Hariharan S

 

The IDE showing names doesn't help much.  The difference is:

foo(10, default, default, default, 12, default)
vs
foo(.x = 10, .z = 12)

Some people might find the second easier to read and understand.  (And some might prefer the first because it doesn't "hide" as much.)

Tony

Alex B

unread,
May 1, 2013, 10:33:03 PM5/1/13
to std-pr...@isocpp.org
Why would we have to chose between the proposed idea and named parameters? Both are interesting. The proposed idea doesn't get in the way of those preferring named parameters (if they ever get into the standard...).
Personally I like it; it's simple, doesn't add complexity and doesn't get in the way of anything. It is not because there are workarounds and that we could live without it that it should not be considered (think about range-based for loops; they were never "needed" but they were added).
About the proposed idea, two things that cross my mind.

1. Default for first parameters (and not only last ones).
It could now also be possible to have default parameters which are not the last ones. This is something new that I would put in the same proposal. For example:
void foo(int=0, int=1, int, int, int) {}
foo
(default, default, 2, 3, 4);

Of course there would be no way to use those default values without using the "default" keyword. (or by using the alternate syntax; see 2.)

2. Omitting parameter instead of the "default" keyword
Why not calling without any keywords between the comas to signify to use the default? Example from the previous post:
foo(10, default, default, default, 12, default);

would become:
foo(10, , , , 12);

Some might prefer it, some might dislike it and stick with the "default" keyword and some would allow both. Personally I don't have anything against any of these options.

Hariharan Subramanian

unread,
May 2, 2013, 12:59:48 AM5/2/13
to std-pr...@isocpp.org
The IDE showing names doesn't help much.  The difference is:

foo(10, default, default, default, 12, default)
vs
foo(.x = 10, .z = 12)

Some people might find the second easier to read and understand.  (And some might prefer the first because it doesn't "hide" as much.)

By IDE showing names I meant this. We type the following
foo(10, default, default, default, 12, default)
But the IDE shows it as
foo(param1: 10, param2: default, param3: default, param4: default, param5: 12);

This is similar to IDE using a special character to show spaces, tabs & newlines. I don't see any difference between IDE doing this and we doing it. The existing code also works with this. We need not have a language feature which can be done better by the IDE. I agree that it will not work with other general purpose editors. Other than that is there any use of named parameters?

Regards,
Hariharan S

Hariharan Subramanian

unread,
May 2, 2013, 1:20:05 AM5/2/13
to std-pr...@isocpp.org
Why would we have to chose between the proposed idea and named parameters? Both are interesting. The proposed idea doesn't get in the way of those preferring named parameters (if they ever get into the standard...).
Personally I like it; it's simple, doesn't add complexity and doesn't get in the way of anything. It is not because there are workarounds and that we could live without it that it should not be considered (think about range-based for loops; they were never "needed" but they were added). 
About the proposed idea, two things that cross my mind.

1. Default for first parameters (and not only last ones).
It could now also be possible to have default parameters which are not the last ones. This is something new that I would put in the same proposal. For example:
void foo(int=0, int=1, int, int, int) {}
foo
(default, default, 2, 3, 4);

Of course there would be no way to use those default values without using the "default" keyword. (or by using the alternate syntax; see 2.)


This is an interesting idea which can also be explored.
 
2. Omitting parameter instead of the "default" keyword
Why not calling without any keywords between the comas to signify to use the default? Example from the previous post:
foo(10, default, default, default, 12, default);

would become:
foo(10, , , , 12);

Some might prefer it, some might dislike it and stick with the "default" keyword and some would allow both. Personally I don't have anything against any of these options.

I considered leaving blank initially. But it does not make the language specification any simpler. Moreover, if you accidentally type an extra comma or leave a comma it might result in a difficult to catch bug. Using default makes the intention explicit.

Regards,
Hariharan S

J. Daniel Garcia

unread,
May 2, 2013, 6:50:05 AM5/2/13
to std-pr...@isocpp.org
Any IDE solution assumes you are using an IDE which is just one way of doing things. It is not the only way of doing things. And this also assumes that the IDE is also used for other tasks (e.g. code reviews).


--
 
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposal...@isocpp.org.

Hariharan Subramanian

unread,
May 2, 2013, 8:24:18 AM5/2/13
to std-pr...@isocpp.org
Any IDE solution assumes you are using an IDE which is just one way of doing things. It is not the only way of doing things. And this also assumes that the IDE is also used for other tasks (e.g. code reviews).

Yes. When we are viewing the code through any workflow we should see the name of the parameters.

There is one more use case for which named parameters are useful. Addition and deletion of parameters. In this case, because of the ordering, the value I originally passed for param_i might go to param_j after the modification. But still, as Alex mentioned, both (middle default parameters and named parameters) do not get into the way of each other. Middle default parameters can exist for its simplicity and named parameters for its power.

Regards,
Hariharan S

J. Daniel Garcia

unread,
May 2, 2013, 9:13:15 AM5/2/13
to std-pr...@isocpp.org
My point about IDE is that you are precluding I am using an IDE. But actually there are other ways (e.g. using vi or emacs or whatever editor you like). Thus the language evolution cannot rest in the assumption that an IDE is being used. Otherwise, we would need to standardize IDEs (what I hope nobody is thinking about).

On the other hand, there is a long history of named parameters in the Ada programming language. I do not have the feeling that they are heavily used, but I do not have experimental data.

Besides, the combination of this proposal and named parameters may encourage interfaces with high number of parameters. I think that is not a desirable thing. Many software quality metrics will say that high number of parameters in an interface increases the complexity and decreases maintainability. Besides, for certain implementations this style may hurt performance.

Thus, I think a relevant question is: 

Do we want to promote styles with high number of function parameters?


Hariharan Subramanian

unread,
May 2, 2013, 9:53:10 AM5/2/13
to std-pr...@isocpp.org
When I first proposed the IDE method, I did not take into consideration the second usage (deletion and addition) of the named parameters. This cannot be solved by the IDE method. Hence IDE method is less than satisfactory.

> Besides, the combination of this proposal and named parameters may encourage interfaces with high number of parameters... Do we want to promote styles with high number of function parameters?
Could you prove the assertion - this proposal in combination with named parameters encourages interface with high number of parameters. Correct me if I am wrong - AFAIK other programming languages do not have this feature and hence there does not exist any prior data.

I think If we are using a default parameter then instead of manually writing the default values when we call the function we just write the keyword "default". Otherwise it should not encourage anything.

Regards,
Hariharan S



--
 
---
You received this message because you are subscribed to a topic in the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this topic, visit https://groups.google.com/a/isocpp.org/d/topic/std-proposals/4tWQEMqEH8s/unsubscribe?hl=en.
To unsubscribe from this group and all its topics, send an email to std-proposal...@isocpp.org.

Vincent Jacquet

unread,
May 2, 2013, 10:58:39 AM5/2/13
to std-pr...@isocpp.org
Actually, named parameters exists in several languages (see <http://en.wikipedia.org/wiki/Named_parameter>). Visual Basic had it for a while and it's been added recently in C# 4.
As far as I know, one of the main reason to add named parameters in c#  was to improve interop with COM, as quite a few methods have a lot of parameters. You might want to take a look at the ConvertToTable method on page http://msdn.microsoft.com/en-us/library/dd264738.aspx). It has lots of parameters therefore named parameters are very usefull for readability in this context.

Yet I am not sure we need this in c++. I think we have better alternatives, such as, for instance, declaring a ConvertToTableSettings struct.

As for allowing "default" parameter in the middle, it has some appeal. I mean it is "not fair" that I must omit value2 if I want to omit value1 (using you example).
But we are speaking of "foo" functions. Do you have real life cases where you want to do that? 

Thanks,
Vincent JACQUET

Hariharan Subramanian

unread,
May 2, 2013, 12:31:36 PM5/2/13
to std-pr...@isocpp.org

Hariharan Subramanian

unread,
May 2, 2013, 12:49:46 PM5/2/13
to std-pr...@isocpp.org
Apologies for my last empty message.

On Thu, May 2, 2013 at 8:28 PM, Vincent Jacquet <vjac...@flowgroup.fr> wrote:
Actually, named parameters exists in several languages (see <http://en.wikipedia.org/wiki/Named_parameter>). Visual Basic had it for a while and it's been added recently in C# 4.
As far as I know, one of the main reason to add named parameters in c#  was to improve interop with COM, as quite a few methods have a lot of parameters. You might want to take a look at the ConvertToTable method on page http://msdn.microsoft.com/en-us/library/dd264738.aspx). It has lots of parameters therefore named parameters are very usefull for readability in this context.

 
What I meant by "other programming languages do not have this feature" was default middle param value and not named params. 

Yet I am not sure we need this in c++. I think we have better alternatives, such as, for instance, declaring a ConvertToTableSettings struct.

As for allowing "default" parameter in the middle, it has some appeal. I mean it is "not fair" that I must omit value2 if I want to omit value1 (using you example).
But we are speaking of "foo" functions. Do you have real life cases where you want to do that? 

I can give my experience but without giving the function name and prototype.
1. Once I had to change the value of the penultimate boolean parameter to an enum. That function was called from 10 different places. I had to change almost each of them as the last parameter they had was non-default.
2. Few functions that I called had 4 or 5 default values in which third or the fourth value was non-default. I had to verify every function every time before calling.

Regards,
Hariharan S

Greg Marr

unread,
May 3, 2013, 12:28:17 AM5/3/13
to std-pr...@isocpp.org
On Thursday, May 2, 2013 12:49:46 PM UTC-4, Hariharan Subramanian wrote:
What I meant by "other programming languages do not have this feature" was default middle param value and not named params. 

It's not a mainstream language, but I work with a product-specific scripting language that allows default middle parameters, and uses the second syntax above with the simple elimination of the parameter: foo(a, b, , , e, f)

This language has been in use for probably 25 years, and shares a lot of syntax with C.

Hariharan Subramanian

unread,
May 3, 2013, 2:15:42 AM5/3/13
to std-pr...@isocpp.org
Thanks for the info Greg. Will you able to offer comments on the assertion "the combination of this proposal and named parameters may encourage interfaces with high number of parameters"?

Regards,
Hariharan S


Greg Marr

unread,
May 3, 2013, 8:57:39 PM5/3/13
to std-pr...@isocpp.org
On Friday, May 3, 2013 2:15:42 AM UTC-4, Hariharan Subramanian wrote:
Thanks for the info Greg. Will you able to offer comments on the assertion "the combination of this proposal and named parameters may encourage interfaces with high number of parameters"?

I don't see what effect middle default parameters would have on named parameters encouraging interfaces with a high number of parameters. It seems to me that they can do that quite well on their own.

Kenshi Takayama

unread,
Aug 16, 2014, 11:08:28 AM8/16/14
to std-pr...@isocpp.org
I really like this proposal. Any progress?

Kenshi

2013年5月4日土曜日 2時57分39秒 UTC+2 Greg Marr:

gmis...@gmail.com

unread,
Aug 16, 2014, 7:37:41 PM8/16/14
to std-pr...@isocpp.org
+1 (as they say)
 
People always want this feature for COM programming on Windows where you have huge numbers of parameters that are best defaulted.
I don't tend to see the situation anywhere else.

but you still end up with excel.insertSheet(0, default,t default,default,default) etc. or whatever, as you say.

Named parameters would seem to be far more favourable to that IMHO.

I'm always leery about using default parameters in any form though, I don't ever seem to have a good experience with them.
I wonder if named parameters might become more useful in web frameworks down the road but I don't know.

It's interesting to know API's people are actually wrestling with that warrant this support. One wonders how common they are and if their design is the fault or not etc.
I know the COM type API's for MS Office made me most think about this topic.


Tony

Hariharan Subramanian

unread,
Aug 17, 2014, 2:02:07 PM8/17/14
to std-pr...@isocpp.org
I started working on it a few days back. I will complete the first draft soon and post it.

Hariharan S


--

---
You received this message because you are subscribed to a topic in the Google Groups "ISO C++ Standard - Future Proposals" group.

To unsubscribe from this group and all its topics, send an email to std-proposal...@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.

Chet

unread,
Aug 18, 2014, 8:38:02 PM8/18/14
to std-pr...@isocpp.org
I have an idea for explicit defaults. An explicit default value will require the use of the default keyword to provide the default value, that is leaving the parmeter off the end of the list would be an error.

I'm not sure how well this would fit with named parameters or the current ideas about default parameters. Perhaps named parameters would be a better solution for the problems this would solve?

Here is an example of what I suggesting:

void foo(int a=1, int b=2); //ok
void bar(int a=explicit 1); //explicit default value 
void mew(int a=1, int b); //explicit default value for a because b does not have a default
void orc(int a, int b=explicit 2); // explicit default value for b
void orc(int a); //since b has an explicit default value we are ok with this overload

int main()
{
foo(); //ok calls foo(1,2)
bar(); //error default is explicit
mew(); //error no default for b
orc(); //error neither overload has defaults for all parameters

foo(9); //ok calls foo(9,2)
bar(9); // calls bar(9)
mew(9); //error no default value for b
orc(9); // calls orc(9) the single parameter overload

foo(default); // calls foo(1,2)
bar(default); // calls bar(1)
mew(default); //error no default for b
orc(default); //error a does not have a default value in either overload

foo(default,5); // calls foo(1,5)
mew(default,5); // calls mew(1,5)
orc(default,5); // error a does not have a default value in either overload

foo(5,default); // calls foo(5,2)
mew(5,default); // error no default value for b
orc(5,default); // calls orc(5,2)

foo(default,default); // calls foo(1,2)
mew(default,default); // error no default value for b
orc(default,default); // error a does not have a default value 

return 0;
}
//end code example

Cheers,

Chet.

Hariharan Subramanian

unread,
Aug 26, 2014, 3:30:47 PM8/26/14
to std-pr...@isocpp.org
I am attaching the first draft of the proposal. It is based on the standards document N3797.pdf dated 2013-10-13.

Hariharan S
Default Values in Middle Parameters.pdf

Nevin Liber

unread,
Aug 26, 2014, 3:52:51 PM8/26/14
to std-pr...@isocpp.org
On 26 August 2014 14:30, Hariharan Subramanian <toh...@gmail.com> wrote:
During the lifecycle of a software, the default value of a parameter can change. If the
default value of type2 changes then no work need to be done. But if the default 
value of type1 changes then wherever a1 was used it should be changed. 

I strongly disagree with "no work need to be done".  Changing a default value is an interface change.  The problem with changing a default parameter is that it is impossible for the author of the callee to determine if a particular caller is using the default because it should not be specified vs. is using it because they knew what the exactly default value is and not specifying it is a convenient shorthand.  I have to visit every caller to see if it is still doing what is intended.
--
 Nevin ":-)" Liber  <mailto:ne...@eviloverlord.com(847) 691-1404

Hariharan Subramanian

unread,
Aug 27, 2014, 3:12:29 PM8/27/14
to std-pr...@isocpp.org
//file1.h
void foo(int a, int b = 1, int c = 2);

//file2.cpp
void foo(int a, int b, int c) { }
static void usefoo() {
  foo(0, default, 3);
}

For the above code one cannot be 100% sure if the programmer meant default or meant 1 masquerading as default. But it gives programmer the option of giving default and actual value for middle parameters. Even if the programmer is reasonable he/she will not be helpless.

Hariharan S




--
Reply all
Reply to author
Forward
0 new messages