已知类型的C ++可变参数函数模板

时间:2013-07-22 15:54:52

标签: templates c++11 variadic-templates variadic-functions

我目前正试图了解一些我可以通过可变参数模板支持做的事情。假设我有这样的函数 -

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是一个void字段的错误。我知道我也可以通过递归来访问包中的参数,但我不确定这会解决我的问题 - 即我希望能够获取相同类型的可变数量的参数。

5 个答案:

答案 0 :(得分:12)

这应该有效:

void foo(int);

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

答案 1 :(得分:6)

如果您知道之前的类型,可以使用函数重载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是不合法的,这与精确度有关,浮点数无法精确表示,并且您引用相同类型的可能性取决于数字的表示方式。

答案 2 :(得分:2)

  

我目前正试图了解一些我可以使用可变参数模板支持做的事情。

假设您要尝试使用可变参数模板,而不是找到问题的任何解决方案,那么我建议您查看下面的代码:

#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;
}

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

答案 3 :(得分:0)

最常见答案的一种变体,如果您愿意,则将拒绝隐式转换为true

exit

答案 4 :(得分:0)

在大多数情况下,使用具有相同类型参数包的可变参数模板是没有意义的,但在启用 c++11 的编译器中将是:

#include <iostream>
#include <tuple>

template <typename ... Args>
void foo(Args ... args) {
    using type = typename std::tuple_element<0, std::tuple<Args...>>::type;
    const auto len = std::tuple_size<std::tuple<Args...>> {};
    type vals[] = {args...};

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

int32_t main(int argc, char** argv) {
    foo(1, 2);
    foo(1.1, 2.2);
    foo("1", "2");
    return EXIT_SUCCESS;
}