Sebastian Karlsson
Sebastian Karlsson

Reputation: 745

C++: passing unknown union to function as argument

So I have something like this:

struct FoodType {
    union {
        int fat = 2;
    } Apple;
    union {
        int fat = 3;
    } Banana;
} FoodType;

And I want to write a function that takes an "unknown" FoodType as argument.

void eatFood(FoodType type) { /* do something */ }

How can this be implemented?

Upvotes: 0

Views: 246

Answers (3)

stefaanv
stefaanv

Reputation: 14392

Alternatives to the enum solution for what you provide in your question is instantiation:

#include <iostream>

struct FoodType {
    FoodType(int f) : fat(f) {}
    int getFat() { return fat; }
    int fat;
};

void eatFood(const FoodType& type) { std::cout << "I ate " << type.getFat() << " grams of fat\n"; }

int main() {
    FoodType apple(2);
    eatFood(apple);
    FoodType banana(3);
    eatFood(banana);
}

or, for more complex situations, polymorphism can be used, but here it seems like overkill:

#include <iostream>

struct FoodType {
    virtual int getFat() const = 0;
};

struct Apple: FoodType {
    int getFat() const { return 2; }
};

struct Banana: FoodType {
    int getFat() const { return 3; }
};

void eatFood(const FoodType& type) { std::cout << "I ate " << type.getFat() << " grams of fat\n"; }

int main() {
    Apple apple;
    eatFood(apple);
    Banana banana;
    eatFood(banana);
}

Upvotes: 2

Max Vollmer
Max Vollmer

Reputation: 8598

Judging from your comments you want enums. C++ has enums:

enum FoodType
{
    Apple,
    Banana
};

void EatFood(const FoodType & foodType)
{
    switch (foodType)
    {
    case Apple:
        /* do something */
        break;
    case Banana:
        /* do something */
        break;
    default:
        /* handle invalid value */
        break;
    }
}

If you need those integer values, do this:

enum FoodType
{
    Apple=2,
    Banana=3
};

If you want strict typing, do this:

enum class FoodType
{
    Apple=2,
    Banana=3
};

(And then in EatFood you have to use FoodType::Apple and FoodType::Banana.)

Upvotes: 1

Cris Luengo
Cris Luengo

Reputation: 60494

Is this what you're after?

struct Food {
  enum class Type { Apple, Banana };
  int fat = 2;
  Type type = Apple;
};

Here you can specify the type, and you can store the fat value as well.

In the question's code, there is a union with a single member. union need more than one member to be useful, the members are stored at the same memory address, so you can only use one of them at the time. And both unions declared a variable with the same name and function, it seems to me that you'd only need one of those.

However, if you have something more complicated in mind, and you really need a union, then you should try something like this:

struct Food {
  enum class Type { Apple, Banana };
  Type type = Apple;
  union {
    int banana;
    double apple;
  };
};
Food food;
food.type = Food::Type::Apple;
food.apple = 2;

Here, you can use either the banana element or the apple element, and you'd use the type element to know which one to use.

But if you need that, you'd be better off using the new std::variant (or boost::variant) if your compiler doesn't yet support it).

Upvotes: 1

Related Questions