如何在编译时使用初始化列表中的可变参数包含不同数量的对象?
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...
,因为您不能(没有风险)多次转发同一个变量。
这是上一个问题的扩展 (
我需要包含不同数量的对象,具体取决于提供的 'define' 和不同的 ctor 参数。第一个参数是一个 'index' 从零到 (NUMBER-1) 的对象,其他参数是可选的。
到目前为止,当只显示单个 'index' 参数时,我没有遇到任何问题,但我仍在努力添加可选参数 Args... args
.
这就是我正在努力做到的。假设我们要在 类
之后实例化 2class 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...
,因为您不能(没有风险)多次转发同一个变量。