我有一些功能
template<typename T>
constexpr Foo make_foo<T>();
基本上将类型映射到Foo
的实例,没有副作用。
现在,我想编写函数magic
,
template<typename Types...>
vector<Foo> magic();
与make_foo相同,但是对于可变参数包;并且在某种程度上,我可以轻松地将所有这些Foo流式传输到std :: cout,或者在循环中迭代它们等等。我意识到这个问题并没有完全明确定义因为我不清楚我正在寻找的相关输出是否是某种可变的值包(看看它在运行时是如何存在的)。
那么,这样做的惯用方法是什么?我注意到Eric Niebler有一个关于metaprogramming library的博客页面似乎是相关的,但似乎有点矫枉过正。就我而言。
答案 0 :(得分:1)
如果您需要Foo
s的向量,那么它只是
template<typename Types...>
vector<Foo> magic(){
return { make_foo<Types>()... };
}
您也可以将它们放入本地数组并随意使用它们:
Foo foos[] = { make_foo<Types>()... };
答案 1 :(得分:0)
访问参数包的各个成员的标准方法是通过递归,从一个时间剥离一个或多个成员。在这种情况下,我们可以使make_foo<T>()
成为一个包装函数,它将参数包传递给工作者函数,而工作函数又调用make_foo<T>()
。因此,假设// Prototypes:
// -----
template<typename T>
constexpr Foo make_foo();
template<typename... Types>
std::vector<Foo> magic();
template<>
std::vector<Foo> magic<>();
template<typename T>
void magic_worker(std::vector<Foo>& vec);
template<typename T, typename U, typename... Types>
void magic_worker(std::vector<Foo>& vec);
// Actual code:
// -----
// The wrapper.
template<typename... Types>
std::vector<Foo> magic() {
std::vector<Foo> vec;
magic_worker<Types...>(vec);
return vec;
}
// Empty parameter pack.
template<>
std::vector<Foo> magic<>() {
return std::vector<Foo>(0);
}
// Only one type left.
template<typename T>
void magic_worker(std::vector<Foo>& vec) {
vec.push_back(make_foo<T>());
}
// At least two types left.
template<typename T, typename U, typename... Types>
void magic_worker(std::vector<Foo>& vec) {
vec.push_back(make_foo<T>());
magic_worker<U, Types...>(vec);
}
一次只能采用一种类型,我们会有类似的结果。
std::cout
不确定这是否是最有效的方式来做你想要的,但它应该工作。如果您愿意,可以通过基于范围的for循环将矢量输出到std::vector<Foo> vec = magic</* args */>();
for (auto& a : vec) {
std::cout << a;
}
。
magic_worker()
有关工作示例,请参阅here。
编辑:如果您想知道为什么<typename T>
的递归版本在包之前有两个不同的模板参数,那么它就可以消除歧义。由于模板包可以没有成员,一个版本需要<typename T, typename... Types>
而另一个版本csv = CSV.new(io, options)
会使编译器混淆,并阻止编译代码。有关详细信息,请参阅here。