我对如何通过使用可变参数模板从元组中读取每个参数感到有点困惑。
考虑这个功能:
template<class...A> int func(A...args){
int size = sizeof...(A);
.... }
我从主文件中调用它,如:
func(1,10,100,1000);
现在,我不知道如何扩展func
的主体以便能够分别读取每个参数,以便我可以将参数存储在数组中。
答案 0 :(得分:12)
您必须为使用第一个N
(通常是一个)参数的函数提供覆盖。
void foo() {
// end condition argument pack is empty
}
template <class First, class... Rest>
void foo(First first, Rest... rest) {
// Do something with first
cout << first << endl;
foo(rest...); // Unpack the arguments for further treatment
}
解压缩可变参数时,它会找到下一个重载。
示例:强>
foo(42, true, 'a', "hello");
// Calls foo with First = int, and Rest = { bool, char, char* }
// foo(42, Rest = {true, 'a', "hello"}); // not the real syntax
然后下一级我们展开之前的Rest
并获得:
foo(true, Rest = { 'a', "hello"}); // First = bool
依此类推,直到Rest
不包含任何成员,在这种情况下解包它会调用foo()
(没有参数的重载)。
如果要存储整个参数包,可以使用std::tuple
template <class... Pack>
void store_pack(Pack... p) {
std::tuple<Pack...> store( p... );
// do something with store
}
然而,这似乎不太有用。
如果包中的所有值都是相同类型,您可以将它们全部存储为:
vector<int> reverse(int i) {
vector<int> ret;
ret.push_back(i);
return ret;
}
template <class... R>
vector<int> reverse(int i, R... r) {
vector<int> ret = reverse(r...);
ret.push_back(i);
return ret;
}
int main() {
auto v = reverse(1, 2, 3, 4);
for_each(v.cbegin(), v.cend(),
[](int i ) {
std::cout << i << std::endl;
}
);
}
然而,这似乎甚至更少有用。
答案 1 :(得分:3)
如果参数都是相同的类型,你可以将参数存储在这样的数组中(使用数组的第一个参数的类型):
template <class T, class ...Args>
void foo(const T& first, const Args&... args)
{
T arr[sizeof...(args) + 1] = { first, args...};
}
int main()
{
foo(1);
foo(1, 10, 100, 1000);
}
如果类型不同,我想你可以使用boost::any
但是我不知道你将如何在给定模板之外找出,哪个项目属于哪种类型(你怎么样)使用存储的值。)
修改强>
如果参数都是相同的类型,并且您希望将它们存储到STL容器中,则可以使用std::initializer_list<T>
。例如,Motti的反向存储值的例子:
#include <vector>
#include <iostream>
#include <iterator>
template <class Iter>
std::reverse_iterator<Iter> make_reverse_iterator(Iter it)
{
return std::reverse_iterator<Iter>(it);
}
template <class T>
std::vector<T> reverse(std::initializer_list<T> const & init)
{
return std::vector<T>(make_reverse_iterator(init.end()), make_reverse_iterator(init.begin()));
}
int main() {
auto v = reverse({1, 2, 3, 4});
for (auto it = v.begin(); it != v.end(); ++it) {
std::cout << *it << std::endl;
}
}
答案 2 :(得分:2)
如果参数有不同的类型,为了坚持数组,你也可以使用std::common_type<>
template<class ...A> void func(A ...args){
typedef typename std::common_type<A...>::type common;
std::array<common, sizeof...(A)> a = {{ args... }};
}
例如,func(std::string("Hello"), "folks")
会创建一个std::string
的数组。
答案 3 :(得分:1)
如果需要在数组中存储参数,可以使用boost::any
数组,如下所示:
template<typename... A> int func(const A&... args)
{
boost::any arr[sizeof...(A)] = { args... };
return 0;
}