I'm working on a large project and I've updated a method that's used by almost all parts of the system; the method now takes another parameter.
I wanted to make the new parameter optional so that I don't have to go and update everyone else's code to make use of it, so I provide a default parameter.
Is there any way I can emit a compiler warning to state that relying on the default parameter is deprecated, only if they're relying on it?
Instead of using a default parameter, you could try using an overloaded function, one that has the extra parameter and one that doesn't, and mark the one without the extra parameter as deprecated. It can call through to the new function, passing in whatever default you want.
Related
Right now, I am trying to call a function in C++ through a Json object. The Json object would provide me with the name of the callee function and all the parameters. I will be able to extract the parameters using a for loop, but I am not sure how I can pass them in. For loop only allows me to pass arguments one by one, and I did not find a way to call a function besides passing in all the arguments at once.
I've made a temporary solution of:
if (parameter_count == 1)
func(param_1);
if (parameter_count == 2)
func(param_1, param_2);
...
This solution seems would not work for all cases since it can only work for functions with a limited number of arguments (depending on how many ifs I write). Is there a better way for this? Thanks!
EDIT: Sorry if I was being unclear. I do not know anything about func. I will be reading func from DLL based on its string name. Since I can't really change the function itself, I wouldn't be able to pass in a vector or struct directly.
Or perhaps did I have the wrong understanding? Are we allowed to pass in a single vector in place of a lot of parameters?
Sorry for making a mess through so many edits on this question. Brandon's solution with libffi works. Thanks!
So the problem as I understand it is that you have a void * pointer (which would come from your platform's DLL loading code) which "secretly" is a pointer to a function with a signature which is only known at runtime. You'd like to call this function at runtime with specified arguments.
Unfortunately, this is not possible to do cleanly with standard C++ alone. C++ cannot work with types that are not present in the program at compile-time, and since there is an infinite number of potential function signatures involved here there is no way to compile them all in.
What you'll want to do instead is manually set up the stack frame on your call stack and then jump to it, either via inline assembly or via some library or compiler extension that accomplishes this for your platform.
Here is a simple example of doing this via inline assembly. (To do this in general you will need to learn your platform's calling convention in detail, and needless to say this will constrain your program to the platform(s) you've implemented this for.)
I haven't actually tried it, but gcc has a compiler extension __builtin_apply that is apparently just meant to forward the arguments from one method wholesale to another but which could perhaps be used to accomplish something like this if you learned the (apparently opaque) description of the method.
[Update: Apparently I missed this in the comments, but Brandon mentioned libffi, a library which implements a bunch of platforms' calling conventions. This sounds like it might be the best option if you want to take this sort of approach.]
A final option would be to constrain the allowed signatures of your functions to a specified list, e.g. something like
switch(mySignature)
{
case VOID_VOID:
dynamic_cast<std::function<void(void)> *>(myPtr)();
break;
case VOID_INT:
dynamic_cast<std::function<void(int)> *>(myPtr)(my_int_arg_1);
break;
// ...
}
(Syntax of the above may not be 100% correct; I haven't tested it yet.) Whether this approach is sensible for your purposes depends on what you're doing.
I am working on another persons C++ code and don't understand why they did something.
They have a notification class that has a public method called check which takes in the time as a parameter
void check(unsigned long time = 1);
Every time the method is called in the code a current time is passed to it.
notification1.check(currentTime);
My question is why did they give the parameter a value when they defined the method? Why not just say,
void check(unsigned long time);
That's because if no argument if provided in function call, default argument value will be used for time which is 1 in this case. This is called Default Argument
If you call check function and provide no argument, default value of 1 will be assigned to time by the compiler. If you pass an argument while calling check function, that passed value will override the default value of time.
When a function has a default argument passed in to it, you are not required to pass an argument while calling that function and you can specify as many default arguments as you want.
Do you have access to the implementation of check function?
since there is default argument specified in function declaration, you can call it without arguments as well. (ex: notification1.check() ) you should explore what is the behaviour of the check(...) function in each of following scenarios
Function call WITH an argument? (i.e. notification1.check(currentTime))?
Function call WITHOUT argument? (i.e. notification1.check())?
As a best practice of coding, these behaviours has to be documented with the member function declaration. if it is not the case, you'll have to explore the implementation.
It's a default argument. http://en.cppreference.com/w/cpp/language/default_arguments explains all you ever wanted to know about this C++ feature.
My question is why did they give the parameter a value when they defined the method?
If the default argument is not used anywhere, i.e. if the function is always called with a non-default argument, then chances are it was a wrong design decision. Perhaps they thought the default argument was useful when they originally designed the code, but it now turned out that there is no useful default value. Or perhaps they think that the default argument may still be useful in the future.
As a matter of fact, 1 is a questionable value for an unsigned long time parameter, which looks a lot like a value representing milliseconds since January 1st 1970. Why not 0?
In Kotlin there are two ways to express an optional parameter, either by specifying default argument value:
fun foo(parameter: Any, option: Boolean = false) { ... }
or by introducing an overload:
fun foo(parameter: Any) = foo(parameter, false)
fun foo(parameter: Any, option: Boolean) { ... }
Which way is preferred in which situations?
What is the difference for consumers of such function?
In Kotlin code calling other Kotlin code optional parameters tend to be the norm over using overloads. Using optional parameters should be you default behavior.
Special cases FOR using defaulted values:
As a general practice or if unsure -- use default arguments over overrides.
if you want the default value to be seen by the caller, use default values. They will show up in IDE tooltips (i.e. Intellij IDEA) and let the caller know they are being applied as part of the contract. You can see in the following screenshot that calling foo() will default some values if values are omitted for x and y:
Whereas doing the same thing with function overloads hides this useful information and just presents a much more messy:
using default values causes bytecode generation of two functions, one with all parameters specified and another that is a bridge function that can check and apply missing parameters with their defaulted values. No matter how many defaulted parameters you have, it is always only two functions. So in a total-function-count constrained environment (i.e. Android), it can be better to have just these two functions instead of a larger number of overloads that it would take to accomplish the same job.
Cases where you might not want to use default argument values:
When you want another JVM language to be able to use the defaulted values you either need to use explicit overloads or use the #JvmOverloads annotation which:
For every parameter with a default value, this will generate one additional overload, which has this parameter and all parameters to the right of it in the parameter list removed.
You have a previous version of your library and for binary API compatibility adding a default parameter might break compatibility for existing compiled code whereas adding an overload would not.
You have a previous existing function:
fun foo() = ...
and you need to retain that function signature, but you also want to add another with the same signature but additional optional parameter:
fun foo() = ...
fun foo(x: Int = 5) = ... // never can be called using default value
You will not be able to use the default value in the 2nd version (other than via reflection callBy). Instead all foo() calls without parameters still call the first version of the function. So you need to instead use distinct overloads without the default or you will confuse users of the function:
fun foo() = ...
fun foo(x: Int) = ...
You have arguments that may not make sense together, and therefore overloads allow you to group parameters into meaningful coordinated sets.
Calling methods with default values has to do another step to check which values are missing and apply the defaults and then forward the call to the real method. So in a performance constrained environment (i.e. Android, embedded, real-time, billion loop iterations on a method call) this extra check may not be desired. Although if you do not see an issue in profiling, this might be an imaginary issue, might be inlined by the JVM, and may not have any impact at all. Measure first before worrying.
Cases that don't really support either case:
In case you are reading general arguments about this from other languages...
in a C# answer for this similar question the esteemed Jon Skeet mentions that you should be careful using defaults if they could change between builds and that would be a problem. In C# the defaulting is at the call site, whereas in Kotlin for non-inlined functions it is inside of the (bridge) function being called. Therefore for Kotlin it is the same impact for changing hidden and explicit defaulting of values and this argument should not impact the decision.
also in the C# answer saying that if team members have opposing views about use of defaulted arguments then maybe don't use them. This should not be applied to Kotlin as they are a core language feature and used in the standard library since before 1.0 and there is no support for restricting their use. The opposing team members should default to using defaulted arguments unless they have a definitive case that makes them unusable. Whereas in C# it was introduced much later in the life cycle of that language and therefore had a sense of more "optional adoption"
Let's examine how functions with default argument values are compiled in Kotlin to see if there's a difference in method count. It may differ depending on the target platform, so we'll look into Kotlin for JVM first.
For the function fun foo(parameter: Any, option: Boolean = false) the following two methods are generated:
First is foo(Ljava/lang/Object;Z)V which is being called when all arguments are specified at a call site.
Second is synthetic bridge foo$default(Ljava/lang/Object;ZILjava/lang/Object;)V. It has 2 additional parameters: Int mask that specifies which parameters were actually passed and an Object parameter which currently is not used, but reserved for allowing super-calls with default arguments in the future.
That bridge is called when some arguments are omitted at a call-site. The bridge analyzes the mask, provides default values for omitted arguments and then calls the first method now specifying all arguments.
When you place #JvmOverloads annotation on a function, additional overloads are generated, one per each argument with default value. All these overloads delegate to foo$default bridge. For the foo function the following additional overload will be generated: foo(Ljava/lang/Object;)V.
Thus, from the method count point of view, in a situation when a function has only one parameter with default value, it's no matter whether you use overloads or default values, you'll get two methods. But if there's more than one optional parameter, using default values instead of overloads will result in less methods generated.
Overloads could be preferred when the implementation of a function gets simpler when parameter is omitted.
Consider the following example:
fun compare(v1: T, v2: T, ignoreCase: Boolean = false) =
if (ignoreCase)
internalCompareWithIgnoreCase(v1, v2)
else
internalCompare(v1, v2)
When it is called like compare(a, b) and ignoreCase is omitted, you actually pay twice for not using ignoreCase: first is when arguments are checked and default values are substituted instead of omitted ones and second is when you check the ignoreCase in the body of compare and branch to internalCompare based on its value.
Adding an overload will get rid of these two checks. Also a method with such simple body is more likely to be inlined by JIT compiler.
fun compare(v1: T, v2: T) = internalCompare(v1, v2)
Usually in my code I need to use specific functions for various variables i.e.
object->SetStatus("var1",1); object->SetAddress("var1",&var1);
object->SetStatus("var2",1); object->SetAddress("var2",&var2);
object->SetStatus("var3",1); object->SetAddress("var3",&var3);
...
My idea is to use a function that will do this automatically by calling it, i.e.
object->function(var1,var2,var3,...);
To achieve that I have to solve 3 issues
I need to read the number of arguments when calling function()
I need to parse somehow the argument names inside the code
Since the variables are not of the same type, I need to find a way to make function() type "transparent"
Since I am newbie in c++ coding, I tried to search fo something similar, but I couldn't find anything.
Any help, advice or remark is more than welcome!
There are multiple ways to do so. One way is make a Base class and all your variable type will inherit from this base class. Then pass a map<string,Base> as an argument to you function. name of variable will be key and value will be actual variables. Iterate through the map and set and assign values to methods.
You could consider some variadic template, if coding in C++11 or C++14. There is considerable literature about that subject (e.g. this tutorial), which is a bit tricky (so explaining it here is not reasonable). Read also about parameter pack
You could also use C style varargs using <cstdarg>
Perhaps std::initializer_list could be useful too.
So here's my question in the function declaration there is an argument and it is already initialized to a certain value. What are the procedures to call this function and use that default value, or is it just a way to document code, telling other programmers what you expect them to use as a value for the parameter? Thank you.
enum File
{
XML = 0,
PDF = 1,
};
Char *SetSection(const File = XML);
If I understand your question correctly, simply calling SetSection with no parameters will do.
SetSection();
The above call gets translated (for lack of a better term) to:
SetSection(XML);
It means that the function can be called without parameters in which case the default value, XML, will be used.
In this case, File is a default argument. Calling SetSection() without arguments will set the File argument to the default value specified in the declaration.
If you call
SetSection();
It will call SetSection(XML) instead.
This is why the optional parameters have to be at the end of all parameters. If you don't provide enough parameters, it will use the default.
XML is the standard parameter.
You can call it with SetSection(); (But SetSection(XML) or SetSection(PDF) are valid, too).
What you are seeing in the declaration is a default argument value.
If you call SetSection(); it is the same as calling SetSection(XML);
You can also call SetSelection(PDF); or use any other valid parameter to override the default.
You may also be seeing the result of an incremental development which started with the function having no parameter and calls to the function scattered throughout the code. Then the alternative file type of PDF was introduced, but the prototype was changed to have a default value, which meant not having to change the existing call site.