使用可变参数模板初始化静态数组

Initialize static array with variadic template

提问人:Zachary Peterson 提问时间:11/5/2022 最后编辑:Zachary Peterson 更新时间:11/5/2022 访问量:58

问:

我有一个包含 Ingredient 类型的静态数组的结构配方,我想用可变参数模板构造它,以用任意数量填充数组。我查看了这里发布的其他问题,主要是:使用可变参数模板创建静态数组,但是当数组填充了{args...}时,数据不是输入的内容。这是在 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
};

使用代码:

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];
    }
}

食谱中的成分表变为 [0] {id=65021,金额=65021,消耗量=false} [1] {id=0, amount=0, consumed=false}

C++ C++17 可变模板

评论

0赞 Neil Butterworth 11/5/2022
为什么所有这些东西都是静态的?
0赞 user17732522 11/5/2022
请使用标准类型或定义您的类型。此外,灵活的数组成员不是标准的 C++。因此,也要添加您正在使用的编译器。
0赞 Zachary Peterson 11/5/2022
Items 是一个无需实例即可在任何地方访问的类,它几乎是一个数据库
0赞 Marek R 11/5/2022
请解释此代码应执行的操作。最好的形式是测试失败(你期望通过,编译错误也是测试失败)。因此,请提供示例 o 用法,它将可视化您的问题中的第一个段落。
0赞 user17732522 11/5/2022
据我所知,唯一一种形式的灵活数组成员需要在创建对象之前手动为整个结构+数组分配足够的空间。你没有在任何地方这样做。您需要首先使用 or 来分配内存,然后将对象放入其中(假设编译器首先支持这种形式的灵活数组成员,我不知道)。你为什么使用这种不寻常的结构呢?为什么不使用?mallocoperator newstd::vector<Ingredient>

答:

0赞 Zachary Peterson 11/5/2022 #1

因此,我发现的解决方案对我来说很有效:

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), ...);
}