Storing function parameters for easy update

Nov 2, 2019 at 11:45am
So I havent really been working on anything it's just a question I had. I was thinking that when you write functions, if you have a few arguments in the argument list, then use that function a ton, then find out later you need to add another argument to the functions argument list, you have to go through and add it to each invokation of that function, which is a pain. Now yes, a properly designed program may mitigate or even eliminate this issue, but lets face it, shit happens.

So I was wondering, is there a way to have one spot for a declaration of an argument list, that a function can use in any instance without it having to update each one?

As an example, lets say i have my function definition stored somewhere:

(Not sure if this would work its just an example to illustrate what im talking about)

ArgumentList = (int x, int y, int z);


void Function(ArgumentList)

This way, if i want to add an argument to the functions argument list, all I have to do is add it in one spot and any instance of that function will have it.
Nov 2, 2019 at 11:52am
Two straightforward ways:
(1) Pass a struct (or class): then you pass a single, compound object with whatever you want as data members.
(2) Or make your function a function member of a struct or class containing your parameters.
Last edited on Nov 2, 2019 at 11:52am
Nov 2, 2019 at 12:14pm
So like this?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>

using namespace std;

struct str
{
	int x{};
	int y{};
	int z{};
} s;

void FunctionTest(str& s)
{
    s.x = 0;
    s.y = 34;
    s.z = 56;

    cout << "X: " << s.x << " Y: " << s.y << " Z: " << s.z << endl;
}

int main()
{
	FunctionTest(s);
}
Nov 2, 2019 at 12:17pm
More usefully like this.

Define a local variable of type Str in main(), pass it to the function, get it back, print it out in main.

(I've capitalised the first letter of your struct - no obligation to do that if you don't want to.)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>
using namespace std;

struct Str
{
	int x{};
	int y{};
	int z{};
};

void FunctionTest(Str& s)
{
    s.x = 0;
    s.y = 34;
    s.z = 56;
}

int main()
{
    Str s;
    FunctionTest(s);
	
    cout << "X: " << s.x << " Y: " << s.y << " Z: " << s.z << endl;
}
Last edited on Nov 2, 2019 at 12:18pm
Nov 2, 2019 at 12:42pm
ah, interesting, thanks!
Nov 2, 2019 at 1:19pm
Is this still a valid way to do this?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include <iostream>
using namespace std;

struct Arguments
{
	int x{};
	int y{};
	int z{};

	float sizeX{};
	float sizeY{};
	float sizeZ{};

} coords, dimensions;

void GetCoordinants(Arguments)
{
	coords.x = 0;
	coords.y = 34;
	coords.z = 56;
}

void GetSize(Arguments)
{
	dimensions.sizeX = 34.99;
	dimensions.sizeY = 32.06;
	dimensions.sizeZ = 64.00;
}

int main()
{
	GetCoordinants(coords);

	cout << "Coords: " << "X: " << coords.x << " Y: " << coords.y << " Z: " << coords.z << endl;

	GetSize(dimensions);

	cout << "Dimensions: " << "X " << dimensions.sizeX << " Y " << dimensions.sizeY << " Z " << dimensions.sizeZ << endl;
}
Last edited on Nov 2, 2019 at 1:23pm
Nov 2, 2019 at 1:38pm
Why are you trying to pass the NAME of a type ("Arguments") rather than an OBJECT of that type?

Neither of your functions uses (or, indeed, could use) its arguments.

It is extremely unclear what you are trying to do. This is becoming an XY problem.
Nov 2, 2019 at 1:56pm
If you add a new argument to a function, then presumably you need to pass different values in different calls to the function. I struggle to understand how you could automatically determine which calls should pass which values.

If the parameter is always the same then it shouldn't be a parameter. If you're initializing values then put them in a class and use a constructor.

But if you really need to add a parameter then pull on your big boy/girl undies and search the code for every call. Make the appropriate changes to each call.

Sure this is grunt work, but it doesn't really take that long. Also, you'll quickly get a reputation as a hero because you can do stuff that others "can't." Sometimes developers say that something is too hard to do when it's really just grunt work that they aren't willing to do. They'll make every excuse in the book for why it's too hard, too error prone, can't be done, will mess up the rest of the system etc. etc. etc. That's when you, Captain Coder, should step in, knuckle down and just do the work. Your boss will think you're amazing.
Nov 2, 2019 at 2:06pm
its not the cleanest, but if you had a very large program you can just use overloading. This works where you need a new parameter for new code, but the old stuff was fine without it, which happens sometimes.

1
2
3
4
5
6
7
8
9
10
void foo (thing a, int b)
{
   stuff;
}

void foo (thing a, int b, oops iforgot)
{
   foo(a, b); 
  use(iforgot);
}


you can also use a default value for new parameters to an extent to solve this:


1
2
3
4
5
void foo (thing a, int b, oops iforgot = derp)
{
   stuff;
}


foo(x,y); //ok
foo(x,y,z); //also ok

if the old code NEEDS to send the new parameter, you have to use the other ideas.

if you have time, do it right though. unnecessary wrappers to patch stuff in that you missed is going to make a mess to read. Its not impossible to follow, but it will leave the reader doing a head-scratch as to WHY.
Last edited on Nov 2, 2019 at 2:13pm
Nov 2, 2019 at 2:24pm
1
2
3
4
struct Arguments
{
  // members
} coords, dimensions;

Why do you stick to that (C) syntax? Would it not be more expressive to write:
1
2
3
4
5
6
7
8
struct Arguments // type definition
{
  // members
};

// global variables
Arguments coords;
Arguments dimensions;


Besides, why have global variables at all?
Last edited on Nov 2, 2019 at 2:26pm
Nov 2, 2019 at 2:39pm
Whoa lots of responses. I was following the documentation on here for the struct and thats why i had the objects declared before the semicolon in the struct.

http://www.cplusplus.com/doc/tutorial/structures/

I was thinking since the objects were declared in the struct I could just pass the name of the struct in the function argument list and just use it that way, that way I could just use any declared object without having to write out all the objects in the function argument list. I see the problem with that now so I reverted it back to this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <iostream>
using namespace std;

struct Arguments
{
	int x{};
	int y{};
	int z{};

	float sizeX{};
	float sizeY{};
	float sizeZ{};

};

void GetCoordinants(Arguments& coords)
{
	coords.x = 0;
	coords.y = 34;
	coords.z = 56;
}

void GetSize(Arguments& dimensions)
{
	dimensions.sizeX = 34.99;
	dimensions.sizeY = 32.06;
	dimensions.sizeZ = 64.00;
}

int main()
{
	Arguments coords, dimensions;
	
	GetCoordinants(coords);

	cout << "Coords: " << "X: " << coords.x << " Y: " << coords.y << " Z: " << coords.z << endl;

	GetSize(dimensions);

	cout << "Dimensions: " << "X " << dimensions.sizeX << " Y " << dimensions.sizeY << " Z " << dimensions.sizeZ << endl;
}


@jonnin thats a good solution, i'll keep that one in mind as well. I know that doing the grunt work is pretty much unavoidable but for me the less i have to keep track of in my head the easier it is to just focus on creating.
Topic archived. No new replies allowed.