1

I have a function that takes different variables with different types and makes calculations with the variables depending on the types.

Is it possible for a class/struct in c++ to pass all public variables to a function?

Something like this:

class some_vars {
int a=3;
double b=5.0;
std::string str="thanks for help";
};

void f(some_vars.commaseparatedvariables);

some_vars.commaseparatedvariables would here be: some_vars.a,some_vars.b,some_vars.str

edit I don't want to enumerate through the class. I just want to pass all public available variables of the class to a function.

edit2 The function can handle a variable number of variables with different types passed to it. So for me it would be natural to pass the class variables and when a change is needed I just have to change them and do not have to change them a second time in the function. (Hope this clears things up.)

hdijohkem
  • 27
  • 7
  • 2
    Why do you want to do this? You can pass a reference to `some_vars` and get each member by name. – Mark Ransom Jun 26 '15 at 18:18
  • 2
    Why not pass by reference? `void f(some_vars &);` – Captain Obvlious Jun 26 '15 at 18:18
  • I dont want to rewrite every variable name again in the function. – hdijohkem Jun 26 '15 at 18:20
  • Pretty sure you're SOL on this one. Any reason not to make `f` a method of some_vars? – user4581301 Jun 26 '15 at 18:22
  • Does that change the problem? Do you have a solution for that? – hdijohkem Jun 26 '15 at 18:24
  • You can create a struct and point to the member variables. I don't know why you would want to do that but thats one way. –  Jun 26 '15 at 18:26
  • I think your best choice (assuming you can't architect out of this mess) with a macro. `f(SOME_VARS_vars(some_vars));`. – David Schwartz Jun 26 '15 at 18:28
  • If you don't want to change the existing function `f`, and if you have a variable `vars` of the `some_vars` type, you have to write `f(vars.a, vars.b, vars.str);`. No escape. – dlask Jun 26 '15 at 18:29
  • @AmiTavory: Good to know but not exactly my question. Thanks never the less. – hdijohkem Jun 26 '15 at 18:36
  • @DavidSchwartz: How would this macro work/look like? Thanks to everyone for the help up to this point. – hdijohkem Jun 26 '15 at 18:37
  • @hdijohkem Something like `#define SOME_VARS_vars(x) (x ## .a, x ## .b, x ## .str)` – David Schwartz Jun 26 '15 at 18:38
  • Please confirm: You do not wish to use the variables. You just want their names. – user4581301 Jun 26 '15 at 18:49
  • @DavidSchwartz But this will only give me the class name plus the variable names - I have to rewrite them again. – hdijohkem Jun 26 '15 at 18:50
  • @user4581301: No - thats easy preprocessor stuff. ;) But thanks. – hdijohkem Jun 26 '15 at 18:51
  • In that case, better reword this line in your question: *edit I don't want to enumerate through the class. I just want to pass all public available variable names of the class to a function.* – user4581301 Jun 26 '15 at 18:58
  • @user4581301: Sorry English is not my native language. Thanks anyway. – hdijohkem Jun 26 '15 at 19:05
  • @hdijohkem No, you only have to write the macro once for each type. You can use it as many times as you want without retyping the names. (A member function that returns a `va_list` is another option.) – David Schwartz Jun 26 '15 at 19:08
  • @DavidSchwartz: Thanks, the idea is good and I have postet this to my code_snippets file for future uses. ;) But I just have to pass the names once to this one function and for me it is a shame to rewrite them and I thought there would be an easy solution for it. – hdijohkem Jun 26 '15 at 19:13
  • @hdijohkem If you only have to do it once, there's no savings to be had in doing it some clever and complex way. You'll just make the code harder to understand. – David Schwartz Jun 26 '15 at 19:15
  • @DavidSchwartz: Maybe you are right, but the problem for this is, that the user of this program has to change the variables of the class to his liking and I wanted to make the editing process as easy as possible for him. Its easier to change them once in a class than to change them and then go an a search for another function somewhere in some other "district" of the program and change them there too. – hdijohkem Jun 26 '15 at 19:26
  • @hdijohkem Then probably use a class member function that returns a `va_list`. – David Schwartz Jun 26 '15 at 19:31
  • @DavidSchwartz: I looked it up. ;) That is no problem- the function can already take any number of arguments. – hdijohkem Jun 26 '15 at 19:43

4 Answers4

2

As others have said. Pass the object by reference to the function and the function will have access to all of the object's public member variables;

void f(some_vars & some) {
    //some.a == 5
}

Better yet, if you don't want to change the object's variables pass it by constant reference.

void f(const some_vars & some);

That is, of course, assuming you have created the f function and still have the power and will to rewrite its header and implementation. Otherwise, you will have to pass each variable individually into the function.

NickLamp
  • 862
  • 5
  • 10
0

If your function defined in this way …

void f(int a, double b, std::string str) {
    // implementation
}

… and you cannot change it, then you have to provide individual parameters explicitly:

some_vars vars;
f(vars.a, vars.b, vars.str);
dlask
  • 8,776
  • 1
  • 26
  • 30
  • My function uses variadic templates with variable types so this is NOT how it is defined. But thanks anyway. – hdijohkem Jun 26 '15 at 18:58
0

This is how NOT to do it but will result in what you are asking for: You simply create a struct with all your class members inside it and you simply create them as pointers to the original variables:

class Test
{
public:
    static struct MyParams
    {
        int* intNumber;
        float* floatNumber;
        double* doubleNumber;
    };

    Test() : 
        intNumber(100),
        floatNumber(100.1f),
        doubleNumber(100.2)
    {
        myParameters.intNumber = &intNumber;
        myParameters.floatNumber = &floatNumber;
        myParameters.doubleNumber = &doubleNumber;
    }

    MyParams& GetAllMyParameters()
    {
        return this->myParameters;
    }

private:
    int intNumber;
    float floatNumber;
    double doubleNumber;
    MyParams myParameters;
};

void CalcAllParams(Test::MyParams* _myParams)
{
    double sum = 0.0;
    sum = *_myParams->intNumber + *_myParams->floatNumber + *_myParams->doubleNumber;
    std::cout << sum << std::endl;
}

int main()
{
    Test test;
    CalcAllParams(&test.GetAllMyParameters());


    std::cin.get();
    return 0;
}

What you can do instead is passing the class as either reference (read why its not a good idea in all cases) or pointer and access all the public member functions if you want like the example below:

class Test
{
public:
    int intNumber;
    float floatNumber;
    double doubleNumber;

    Test()
    {
        intNumber = 1;
        floatNumber = 1.f;
        doubleNumber = 1.0;
    }
};

void CalcAllParams(Test* _testClassObject)
{
    double sum = 0.0;
    sum = (_testClassObject->intNumber + _testClassObject->floatNumber + _testClassObject->doubleNumber);
    std::cout << sum << std::endl;
}

int main()
{
    Test test;
    CalcAllParams(&test);


    std::cin.get();
    return 0;
}
0

Not really direct but you can use std::tuple and a helper function:

auto to_tuple(const some_vars& s)
{
    return st::tie(s.a, s.b, s.str); // or std::make_tuple
}

and transform your

template <typename...Ts>
void f(Ts&&...);

into

template <typename...Ts>
void f(std::tuple<Ts...>& tuple);
Jarod42
  • 203,559
  • 14
  • 181
  • 302