12

I'm currently trying to get my head around some of the things I can do with variadic template support. Let's say I have a function like this -

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

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

This code works because I assume beforehand that the arguments will be integers, but obviously will fail if I provide something else. If I know that the parameter packs will contain a particular type in advance, is there some way that I can do without the templating and have something like -

void foo(int ... a)

I have tried doing this, but the compiler gave an error about foo being a void field. I know that I can also access the parameters in the pack through recursion, but I'm not sure this will fix the problem that I have - namely I want to be able to take a variable number of arguments of the same type.

4

5 回答 5

15

这应该有效:

void foo(int);

template<typename ...Args>
void foo(int first, Args... more)
{
   foo(first);
   foo(more...);
}
于 2015-06-26T15:55:16.733 回答
9

如果您以前知道类型,则可以使用函数重载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>();

float但是您必须记住,它不适std::string用于例如:您将以 . 结尾'float': illegal type for non-type template parameterfloat作为 a 是不合法的non-type template parameter,这与精度有关,浮点数无法精确表示,您引用同一类型的可能性取决于数字的表示方式。

于 2013-07-22T17:02:39.573 回答
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;
}

foo2和你的区别在于你在运行时foo将参数传递给,在编译时传递给,所以对于你使用的每个参数集,编译器都会生成单独的函数体。foofoo2foo2

于 2013-07-22T20:29:06.107 回答
1

int最佳答案的变体,如果这是您的偏好,它将拒绝隐式转换:

#include <type_traits>

void foo(int);

template<typename Arg1, typename ...Args>
void foo(Arg1 first, Args... more)
{
   static_assert(std::is_same_v<Arg1, int>, "foo called with non-int argument");
   foo(first);
   foo(more...);
}
于 2019-11-22T01:35:29.630 回答
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;
}
于 2021-06-08T14:43:43.340 回答