如何在编译时使用初始化列表中的可变参数包含不同数量的对象?

How to include different number of objects at compile time with variadic arguments in the initializer list?

这是上一个问题的扩展 ()

我需要包含不同数量的对象,具体取决于提供的 'define' 和不同的 ctor 参数。第一个参数是一个 'index' 从零到 (NUMBER-1) 的对象,其他参数是可选的。

到目前为止,当只显示单个 'index' 参数时,我没有遇到任何问题,但我仍在努力添加可选参数 Args... args.

这就是我正在努力做到的。假设我们要在 类

之后实例化 2
class Output
{
public:
    explicit Output(uint32_t idx) : m_idx(idx) { printf("ctor: %u\n", m_idx); };
private:
    uint32_t m_idx = -1;
};

class Input
{
public:
    explicit Input(uint32_t idx, std::string name) : m_idx(idx), m_name(name) { printf("ctor: %u [%s]\n", m_idx, m_name.data()); };
private:
    uint32_t m_idx = -1;
    std::string m_name;
};

有 2 个模板可以使用顺序索引进行实例化

template<typename T, typename... Args, typename TInts, TInts... I>
constexpr auto MakeArrayHelper(Args... args, std::integer_sequence<TInts, I...>)
{
    return std::array<T, sizeof...(I)>{ (I)..., std::forward<Args>(args)... };
}

template <typename T, size_t Count, typename... Args, typename BaseType = uint32_t>
constexpr auto MakeArray(Args... args)
{
    return MakeArrayHelper<T>((args)..., std::make_integer_sequence<BaseType, Count>());
}

我想像那样实例化 类

    auto outputs = MakeArray<Output, 5>();
    auto inputs = MakeArray<Input, 3>(std::string("Analog"));

    expanded into:
std::array<Output, 5> = { Output{0}, Output{1}, Output{2}, Output{3}, Output{4} };
std::array<Input, 3> = { Input{0, "Analog"}, Input{1, "Analog"}, Input{2, "Analog"} };

这给我留下了一个编译错误:could not deduce template argument for 'TInts'

你能帮我理解我做错了什么吗? 谢谢。

如果没有完整的示例,很难给出完整的答案,但是...我在 MakeArrayHelper()

中看到了一些问题

首先,可变参数包必须在最后位置,否则推导失败。

所以,而不是

template<typename T, typename... Args, typename TInts, TInts... I>
constexpr auto MakeArrayHelper(Args... args, std::integer_sequence<TInts, I...>)

你可以试试

template<typename T, typename TInts, TInts... I, typename... Args>
constexpr auto MakeArrayHelper(std::integer_sequence<TInts, I...>, Args ... args)

其次:如果你想使用转发,args参数必须是转发引用

template<typename T, typename TInts, TInts... I, typename... Args>
constexpr auto MakeArrayHelper(std::integer_sequence<TInts, I...>, Args && ... args)
// .....................................................................^^

第三:在函数中你声明了一个std::array<T, sizeof...(TInts)>但是你用

初始化了它
{ (I)..., std::forward<Args>(args)... };

一系列 sizeof...(TInts) 和一些 args....

我不明白你想要得到什么,但这显然是错误的。

--- 编辑 ---

或者也许我明白你想要什么......如果我理解正确,你想要的是(注意:代码未经测试)

template <typename T, typename TInts, TInts... I, typename ... Args>
constexpr auto MakeArrayHelper (std::integer_sequence<TInts, I...>, Args const & ... args)
{
    return std::array<T, sizeof...(I)>{ T{I, args...} ... };
}

template <typename T, std::size_t Count, typename BaseType = std::uint32_t, typename ... args>
constexpr auto MakeArray (Args const & ... args)
 {
    return MakeArrayHelper<T>(std::make_integer_sequence<BaseType, Count>(), args...);
 }

避免在 MakeArrayHelper() 中转发 args...,因为您不能(没有风险)多次转发同一个变量。