How to determine whether function parameter was automatically set to default value or was set explicitly in C++?
Asked Answered
A

3

7

I'm quite sure this is not possible, but if someway exists (maybe through compiler-provided macros), it would be very useful for me, so I am posting it here. Suppose I have a function:

void func( int param1, bool param2=false){ ... }

param2 has been given a default value here. Is there any mechanism to determine if param2 was explicitly set to its default value false or was it passed automatically? In other words, from within function func, is it possible to distinguish between the following two calls? I am using Microsoft Visual C++ Compiler.

func(1, false);

and

func(1);
Angst answered 15/9, 2014 at 7:38 Comment(3)
If you need to distinguish between these two probably it's better to create two distinct overloadsEmilio
It may be an XY problem. What are you trying to do that would need that?Denticulate
I agree: overloads is the cleanest wayCatalyze
P
4

You can't distinguish the way you're asking, but you can do this:

void func(int param1, boost::optional<bool> param2=boost::none);

Then you can check if param2 is none or not (it has its own operator bool). If it's set, it means it was passed in. Call sites will look the same as before, because an optional can be implicitly constructed from its value type.

Puri answered 15/9, 2014 at 7:47 Comment(0)
H
2

http://coliru.stacked-crooked.com/a/f6bcee72b5c957d1

#include <iostream>

struct CheckDefault {
    CheckDefault() : value(false), param_default(true) {}
    CheckDefault(bool b) : value(b), param_default(false) {}
    bool value;
    bool param_default;
};

void func(int param1, CheckDefault s = CheckDefault()) {
    if (s.param_default)
        std::cout << "with default, ";
    else
        std::cout << "not default, ";
    if (s.value)
        std::cout << "and value is true" << std::endl;
    else
        std::cout << "and value is false" << std::endl;
}

int main() {
    func(5);
    func(5, false);
    func(5, true);
}

The output:

$ ./test2
with default, and value is false
not default, and value is false
not default, and value is true

There needs to be more information than just the single bool so we introduce a second bool and wrap them two together in a new type. Calling the function with an explicit bool triggers the CheckDefault constructor that takes a bool as the only argument. This constructor also initializes param_default to false. Calling without an explicit bool triggers the constructor that takes no arguments. It initializes records s.value with false but sets param_default to true to note that this was a default.

Edited to show inputs for both true and false.

The suggestion by others to use an overload is a good one. To be more explicit, here's what that would look like:

void func(int param1) {
    bool b = false;
    // do stuff ...
}

void func(int param1, bool b) {
    // do stuff ...
}
Horsehide answered 15/9, 2014 at 7:52 Comment(0)
B
1

The value of false is the same whether it is set by default or some other mechanism (note also that default parameters are resolved at compile-time, so there is absolutely no way at runtime to check whether it is given or not).

You could write two functions:

void func( int param1, bool param2 )
{
  ...
}

void func( int param1 )
{
  ... do things differently ...
  func( param1, false );
}

(It may be that you need to call func( int ) from func (int, bool) instead, of course).

Another option would be to change your bool to some user-defined type:

enum TriState { False, True, Unknown };

void func( int param1, TriState parma2 = Unknown )
{
  ... 
}

Of course, you will now need to change all true to True, and false to False, and you can have problems because if (someTriStateVar) is true for Unknown too.

Billion answered 15/9, 2014 at 7:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.