2013-07-22 64 views
6

我目前正试图让我的头可以用variadic模板支持来做一些事情。比方说,我有这样的功能 -已知类型的C++可变参数函数模板

template <typename ... Args> 
void foo(Args ... a) 
{ 
    int len = sizeof...(tail); 
    int vals[] = {a...}; 
    /* Rest of function */ 
} 

/* Elsewhere */ 
foo(1, 2, 3, 4); 

此代码的工作,因为我事先假设的争论将是整数,但很明显,如果我提供别的东西将失败。如果我知道的参数包将包含在事先特定的类型,有一些方法,我可以不用模板,并有一些像 -

void foo(int ... a) 

我试图这样做,但是编译器给了一个错误关于foo是一个无效的领域。我知道我也可以通过递归访问包中的参数,但我不确定这会解决我所遇到的问题 - 也就是说,我希望能够获取可变数目的相同类型的参数。

+1

你可以用'enable_if',以确保所有类型的*是*整数。 –

+2

如果你潜入一堆整数,代码将起作用。如果你给它别的东西,它不起作用。看起来任务完成。哪里有问题? –

+0

我想问题是在编译时是否可以确保它们是整数。 – znby

回答

3

如果你知道之前的类型,你可以使用函数重载与std:initializer_list

#include <initializer_list> 
#include <iostream> 

void foo(std::initializer_list<int> l) 
{ 
    for (auto el : l) 
     // do something 
} 

void foo(std::initializer_list<float> l) 
{ 
} 

void foo(std::initializer_list<std::string> l) 
{ 
} 

int main() 
{ 
    foo({1, 2, 3, 4 }); 
    foo({1.1f, 2.1f, 3.1f, 4.1f }); 
    foo({ "foo", "bar", "foo", "foo" }); 
    return 0; 
} 

如果您使用Visual Studio 2012,您可能需要Visual C++ Compiler November 2012 CTP

编辑:如果你仍然想使用可变参数模板,你可以这样做:

template <int ... Args> 
void foo() 
{ 
    int len = sizeof...(Args); 
    int vals[] = {Args...}; 
    // ... 
} 

// And 

foo<1, 2, 3, 4>(); 

但你要记住,它不与floatstd::string例如工作:你会'float': illegal type for non-type template parameter结束。 float作为non-type template parameter不合法,这与精度有关,浮点数不能精确表示,并且您指的是相同类型的可能性取决于数字的表示方式。

+0

如果你需要知道编译时的参数个数,这个解决方法还不够,因为'initializer_list'不提供'constexpr size()'成员。 AFAIK,没有办法用'is_same <>/is_convertible <>'检查变量模板。 – user2523017

+0

@ user2523017你说得对,用这个解决方案我们在编译时不能有参数个数。 –

1

我目前正试图让我的头部可以用variadic模板支持做些事情。

假设你想与可变参数模板实验,没有发现任何解决您的问题,那么我建议您看看下面的代码:

#include <iostream> 

template<int ...Values> 
void foo2() 
{ 
    int len = sizeof...(Values); 
    int vals[] = {Values...}; 

    for (int i = 0; i < len; ++i) 
    { 
     std::cout << vals[i] << std::endl; 
    } 
} 

int main() 
{ 
    foo2<1, 2, 3, 4>(); 

    return 0; 
} 

foo2之间的区别你foo是您在运行时将参数传递给foo,并且在编译时传递给foo2,因此对于您使用的每个参数集,编译器都会生成单独的foo2函数体。

10

这应该工作:

void foo(int); 

template<typename ...Args> 
void foo(int first, Args... more) 
{ 
    foo(first); 
    foo(std::forward(more)...); 
} 
+0

这个答案更适合OP要求的内容。这个解决方案唯一的缺点是递归部分。但现在我可以看到更好的解决方案,甚至不使用C++ 17和折叠表达式。 – mic

相关问题