codeNoob
codeNoob

Reputation: 77

Return struct object from fuction dependent on numbers of parameters and assign it to object of general struct

I try to explain that. I need a function which gets different numbers of parameters (2,3 or even more) and based on it returns corresponding object of struct:

someStruct funcReturn(bool par1, bool par2, ...)
{
    someStruct temp;
    if (par1)
    {
        //...
    }
    if (par2)
    {
        //...
    }
    ...
    return temp;
}

Structs is very simple:

struct ReturnTwo
{
   int one;
   int two;
};

struct ReturnThree
{
   int one;
   int two;
   int three;
};

And in the end I need to assign the result of this function to a general structure consisting of four objects (missing elements are initialized 0):

struct ReturnFour
{
   int one;
   int two;
   int three;
   int four;
};
...
ReturnFour returnFour = funcReturn(true, false, ...)

My question can be divided into two parts:

  1. Is there a way to work with different numbers of parameters in function and specify a logic of it into the function? Using templates provides that?

  2. How can I assign one struct to another without changing the organization of struct? Something like a auto for struct? Of course I can solve that through С-style:

    ReturnFour returnFour = {funcReturn(true, false).one,funcReturn(true, false).two,0 ,0}
    

But I think there is a more convenient way. Thank you!

Upvotes: 1

Views: 76

Answers (3)

wally
wally

Reputation: 11002

The following solution uses templates, C++17 structured bindings and a std::tuple return type to allow for any number of arguments. As an example all the bool values that were converted to int values are added together.

#include <tuple>

int translate(bool par) // logic to translate a bool to an int
{
    if (par) {
        return 5;
    }
    else {
        return -3;
    }
}

template <typename T>
struct ToInt {
    using Type = int;
};

template <typename... Targs>
std::tuple<typename ToInt<Targs>::Type...> funcReturn(Targs... Fargs)
{
    return { translate(Fargs)... };
}

int main() {
    auto [par1, par2, par3, par4] = funcReturn(true, false, true, true);
    int total = par1 + par2 + par3 + par4; // total == 12
}

demo

Upvotes: 1

Useless
Useless

Reputation: 67723

Just return a ReturnFour always. Returning different types - even if they're subsets of ReturnFour, means you have to write conversion operators or converting constructors, and that's extra work with no benefit visible in this context.

That leaves your overloads looking like

ReturnFour funcReturn(bool p1) { return {42}; }
ReturnFour funcReturn(bool p1, bool p2) { return {42, 53}; }

and the un-used members of the return struct will be value-initialized to zero.

Upvotes: 1

Chris Uzdavinis
Chris Uzdavinis

Reputation: 6131

Would overloaded functions work for you?

ReturnOne funcReturn(bool par1) { ... }

ReturnTwo funcReturn(bool par1, bool par2) { ... }

Etc? Another possibility is to return a struct of optionals, or a bunch of ints and flags to represent which are present.

If you intend for the runtime value of the parameters (rather than the number of them) to determine what type your function returns, then that's not possible. In that case the best you can do is one of the dynamic suggestions I gave above, since it must return just one type and you presumably want that type to indicate which values it contains.

A final idea is if your boolean values are known at compile time, you could use template parameters instead of function arguments, and then have different specializations so the combination of true/false values could select a proper specialization.

Upvotes: 1

Related Questions