0

I have a struct Recipe that houses a static array of type Ingredient, I want to construct it with a variadic template to fill the array with an arbitrary amount. I've looked at other questions posted here, mainly: Create static array with variadic templates, but when the array is filled with {args...}, the data isn't what was put in. This is in msvc.

struct Ingredient
{
    constexpr Ingredient(U16 id, U16 amount = 1, bool consumed = true) : id{ id }, amount{ amount }, consumed{ consumed } {}

    U16 id;
    U16 amount;
    bool consumed;
};
struct Recipe
{
    template<typename... Args>
    constexpr Recipe(U16 result, U16 amount, U8 benchLevel, const Args&... args) :
        result{ result }, amount{ amount }, benchLevel{ benchLevel }, ingredientCount{ sizeof...(args) }, ingredients{ {args...} }
    {
    }

    U16 result;
    U16 amount;
    U8 benchLevel;

    U16 ingredientCount;
    Ingredient ingredients[];
};
class Items
{
public:
    static const Item* GetItem(U16 id) { return items[id]; }
    static const Recipe** GetRecipes() { return recipes; }

private:
    static const Item* items[];
    static const Recipe* recipes[];

    Items() = delete;
};
inline const Recipe* Items::recipes[]
{
    new Recipe(21, 1, 0, Ingredient{11}, Ingredient{12}),
    new Recipe(22, 1, 0, Ingredient{11}, Ingredient{12}),

    nullptr
};

Usage code:

void FillCraftingMenu()
{
    const Recipe** recipes = Items::GetRecipes();

    const Recipe* recipe = recipes[0];

    U16 i = 0;
    while (recipe)
    {
        bool found = true;

        for (U16 j = 0; j < recipe->ingredientCount; ++j)
        {
            found &= inventory->ContainsItem(recipe->ingredients[j].id, recipe->ingredients[j].amount);
        }

        if (found)
        {
            //TODO: put up recipe
            Logger::Debug("Recipe found: {}", recipe->result);
        }

        recipe = recipes[++i];
    }
}

the ingredients list in the recipes becomes [0] {id=65021, amount=65021, consumed=false} [1] {id=0, amount=0, consumed=false}

12
  • why are all these things static? Commented Nov 4, 2022 at 16:18
  • Please use standard types or define what your types are. Also, flexible array members are not standard C++. So add the compiler you are using as well. Commented Nov 4, 2022 at 16:20
  • Items is a class to be accessed anywhere without an instance, it's pretty much a database Commented Nov 4, 2022 at 16:20
  • Please explain what this code should do. Best form is failing test (which you expect to pass, compilation error is also a test failure). So please provide example o usage which will visualize fist paragraph from your question. Commented Nov 4, 2022 at 16:22
  • The only form of flexible array member I am aware of requires manually allocating sufficient space for the whole structure+array before creating the object. You are not doing that anywhere. You would need to use malloc or operator new first to allocate the memory, then placement-new the object into it (assuming this form of flexible array member is supported by the compiler in the first place, which I don't know about). Why do you use such an unusual construction though? Why not use a std::vector<Ingredient>? Commented Nov 4, 2022 at 16:34

1 Answer 1

0

So the solution I found worked well for me was:

template<typename... Args>
constexpr Recipe(U16 result, U16 amount, U8 benchLevel, const Args&... args) :
    result{ result }, amount{ amount }, benchLevel{ benchLevel }, ingredientCount{ sizeof...(args) }, ingredients{ (Ingredient*)malloc(sizeof(Ingredient) * ingredientCount) }
{
    U16 i = 0;
    (void(ingredients[i++] = args), ...);
}
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.