Can I set a default argument from a previous argument?
Asked Answered
B

7

61

Is it possible to use previous arguments in a functions parameter list as the default value for later arguments in the parameter list? For instance,

void f( int a, int b = a, int c = b );

If this is possible, are there any rules of use?

Billfish answered 10/12, 2009 at 13:5 Comment(0)
G
88

The answer is no, you can't. You could get the behaviour you want using overloads:

void f(int a, int b, int c);
inline void f(int a, int b) { f(a,b,b); }
inline void f(int a)        { f(a,a,a); }

As for the last question, C doesn't allow default parameters at all.

Gillie answered 10/12, 2009 at 13:10 Comment(3)
Why did you inline only two of the functions?Carbonize
@DavidDoria: We've no idea whether the main overload can or should be inlined - that's beyond the scope of the question. The others simply call the main overload, and so can trivially be inlined.Gillie
Too bad we can't do this with constructors. I guess C++20 has designated initializers which would allows a similar pattern.Dactylic
N
39

No, that is not legal C++. This is specified in section 8.3.6/9 of the C++ Standard:

Default arguments are evaluated each time the function is called. The order of evaluation of function arguments is unspecified. Consequently, parameters of a function shall not be used in default argument expressions, even if they are not evaluated.

and:

int f(int a, int b = a); // error: parameter a used as default argument

And C89 at least does not support default parameter values.

Nazareth answered 10/12, 2009 at 13:8 Comment(0)
A
7

As a potential workaround, you could do:

const int defaultValue = -999; // or something similar

void f( int a, int b = defaultValue, int c = defaultValue )
{
    if (b == defaultValue) { b = a; }
    if (c == defaultValue) { c = b; }

    //...
}
Ahithophel answered 10/12, 2009 at 13:10 Comment(1)
This will resolve default value at run time. Mike's approach is resolved at compile time. Also, this supposes that the type (here int) may have a special "default" flag value (here -999), and what you do is dangerous : if somehow -999 is passed as a real value this will not work as expected...Eximious
M
3

This is not possible

Mandy answered 10/12, 2009 at 13:8 Comment(0)
O
3

No, you cannot do that.
You will surely get an error "Local variable may not appear in this context".

Orchestra answered 10/12, 2009 at 13:9 Comment(0)
S
1

Your first idea might be to do something like this :

void something(int a, int b=-1, int c=-1){
    if(b == -1)
        b = a;
    if(c == -1)
        c = b;
}

I used -1 because this function only works with positive values. But what if someone uses my class and makes a mistake which ends up sending -1 to the method? It would still compile and execute, but the result would be unpredictable for the user. So the smart thing to do would be to remove any default argument and instead make a bunch of methods with the same name like this:

void something(int a, int b, int c){
    /* Do something with a, b and c */
}

void something(int a){
    something(a, a, a);
}

void something(int a, int b){
    something(a, b, b);
}

It doesn't really take much longer to code, and if someone uses it in a programming interface with auto-complete features, it will show the 3 possible prototypes.

Scratches answered 25/9, 2013 at 0:58 Comment(0)
Q
0

I do not think you can do that as that is an illegal syntax. But however, consult the C99 standard in pdf format (n1136.pdf).

However, you may get around this by using static as in declaring the variables static and using them within the function f

static int global_a;

/* In some other spot where you are calling f(), do this beforehand */
/* global_a = 4; f(); */

void f(void){
   int a = global_a;
   b = c = a;
   /* ..... */
}

Kudos to Michael Burr for pointing out my error! :)

It sounds like you need to rethink your code and change it around for something like that.

Quorum answered 10/12, 2009 at 13:15 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.