Can I set a default argument from a previous argument? - c++

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?

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.

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.

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; }
//...
}

This is not possible

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

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.

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.

Related

Best way to make both a compile-time and runtime version of a function

I have a function that will be called by both compile-time and runtime functions (gtest and python ctypes). I need a templated version and one with the templated variables as function parameters. For example
template<int A, int B, int C>
void function_compiletime(int a, int b, int c) {
// code section 1
}
void function_runtime(int a, int b, int c, int A, int B, int C) {
// code section 2
}
Where // code section 1 is identical to // code section 2. I am cautious that I might accidentally alter something in // code section 1 and not in // code section 2. How can enforce that the body of the functions should be identical?
Best way to make both a compile-time and runtime version of a function
How can enforce that the body of the functions should be identical?
By defining a single constexpr function:
constexpr void
function_runtime(int a, int b, int c, int A, int B, int C)
{
// code section
}

How to employ a variable as parameter inside template of the Eigen::Map class

I encountered the following issue in Eigen taking a set of elements uniformly spaced within a vector employing the class Map.
void func (int A, int B)
{
Eigen::Map<VectorXf,0,Eigen::InnerStride<B> > myMap(v.data() + B - 1, A);
}
The issue is in the 3rd argument of the template "Eigen::InnerStride". The compiler says "error: 'B' is not a constant expression".
I tried to fix as follows:
constexpr int varToConst(int arg)
{
return arg;
}
void func (int A, int B)
{
Eigen::Map<VectorXf,0,Eigen::InnerStride<varToConst(B)> > myMap(v.data() + B - 1, A);
}
but I get the same error. The int B variable is passed by the main and unfortunately, inside the main, it cannot be a const.
Thank you in advance for any help.
You can use dynamic stride, like this:
void func (int A, int B) {
Eigen::Map<VectorXf,0,Eigen::InnerStride<>> myMap(v.data() + B - 1, A, Eigen::InnerStride<>(B));
}
If this section is performance critical, and if the number of feasible B's is small (like - maybe the only valid values are B=2 and B=3), then you can also template func() on B's value. Then you would have something like template <int B> func(int A), and func<2>(/*A=*/10); at the call site.

Passing a single argument to a multi argument function

I have a variable let say int c in a given function. I want to pass it to the other class.let say it is
function(int a, int b, int c);
I want only to pass the third argument while ignore the first two.
i.e. : I just want to pass int c, as function (c) and it just pass it to the third argument. I don't want to pass it like function(0,0,c); .. Is there any possibility. Please advise.
Looks like you want to do function overloading. Something like this-
function(int a, int b, int c);
function(int c);
inside second function you can call first function with appropriate values for a and b
You can have default values for your function:
void function(int c, int a = 0, int b = 0);
or you can overload your function:
void function(int a, int b, int c) {
//implementation 1
}
void function(int c) {
function(0, 0, c);
}
You could in both cases use it like this:
function(c);
Note : when we use default values, in function definition the argument with default values must be the last in order for example :
void function(int a = 0, int b = 0, int c)
is not a valid format.
When you have the situation where function(c) is equivalent to function(0, 0, c), it sounds like a poor design. Normally, you can use default argument values for the parameters starting from the end. It would make sense if function(c) were equivalent to function(c, 0, 0).
You can accomplish that easily by declaring the function as:
void function(int c, int a = 0, int b = 0);
I realize that you can accomplish your goal by overloading function as:
void function(int c)
{
function(0, 0, c);
}
but it still appears to be a poor interface to me.
Imho already with three parameters it is worth to structure them
struct foo {
int a;
int b;
int c;
};
allowing to have a nicer function interface
void function(foo f);
How does this help? You can provide a default constructor and let the user set only those fields that are not default:
struct foo {
int a;
int b;
int c;
foo() : a(0),b(0),c(0) {}
};
foo f;
f.b = 12;
f.c = 32;
function(f);
Now any combination of default / non-defaults is possible.
One could argue that the struct isnt really necessary and the problem is just shifted to the constructor of foo or the need to correctly set the members, but I think this is a valid approach that was missing from the other answers. (btw I am not claiming that my example here demonstrates best pratice, but the details would matter on the exact use case)

Ignore reference function argument

I have function with this signature (I can not edit it):
void foo(int a,int b, int& c);
I want to call it but I do not care about the getting c. Currently I do this:
int temp;
foo(5,4,temp);
//temp never used again
My solution seems dumb. What is the standard way to ignore this argument.
There is none.
If your main concern is about polluting the current stack with a temp variable, a wrapper function like this should suffice:
void foo_wrapper(int a, int b)
{
int temp; foo(a, b, temp);
}
I would write an overload that turns the output argument into a normal return value. I really don't like output arguments and think that they should be avoided.
int foo(int a, int b) {
int tmp = 0;
foo(a,b, tmp);
return tmp;
}
In your program, you just this overload and either ignore the return value or use it.
This is an over engineered solution, so I don't actually recommend it as the first option in production code.
You can create a class to help you easily ignore these kinds of arguments:
template <class T>
struct RefIgnore
{
static inline T ignored_{};
constexpr operator T&() const
{
return ignored_;
}
};
template <class T>
constexpr RefIgnore<T> ref_ignore{};
void foo(int a,int b, int& c);
auto test()
{
foo(2, 3, ref_ignore<int>);
}
Instead of reference you can pass it as a pointer
void foo(int a,int b, int *c = NULL);
in calling place you can either have it as
foo(5, 6);
or if you want to pass the 3rd argument then you can have it as
int n = 3;
foo (1, 2, &n);

Optional argument passing in c++

Need's formatting, editing will take some time.
I cannot tell what you're asking but I'm going to attempt to interpret it as what I read..
void function_one(int a, int b = 3);
void function_two(int a);
void function_one(int a, int b)
{
function_two(b); //pass second argument to function two..
}
void function_two(int a)
{
function_one(5);
}
Note that the above is infinite recursion due not having a base case condition.