Can c++11 parameter packs be used outside templates?

后端 未结 4 1357
慢半拍i
慢半拍i 2020-12-24 06:44

I was wondering if I could have parameter packs consisting of a single, explicitly specified, type. For example, something like this:

#include 

        
4条回答
  •  误落风尘
    2020-12-24 07:24

    void foo(int... args) {}
    

    No you cannot write that.

    But you can have the same effect with this approach:

    template
    void foo(Ints... ints) 
    {
       int args[] { ints... }; //unpack ints here
       //use args
    }
    

    With this approach, you can pass all int if you want. If any argument passed to foo is not int or convertible to int, the above code will result in compilation error, as it would be the case with int ...args approach if it were allowed.

    You could also use static_assert to ensure all Ints are indeed int if you want that behaviour:

    template
    void foo(Ints... ints) 
    {
       static_assert(is_all_same::value, "Arguments must be int.");
    
       int args[] { ints... }; //unpack ints here
       //use args
    }
    

    Now you've to implement is_all_same meta-function which is not difficult to implement.

    Alright, this is the basic idea. You can write more sophisticated code with variadic templates and with the help of some utility meta-functions and helper functions.

    For lots of work that you can do with variadic arguments, you don't even need to store in args[] array, e.g if you want to print the arguments to std::ostream, then you could just do it as:

    struct sink { template sink(T && ... ) {} };
    
    template
    void foo(Ints... ints) 
    {
        //some code
    
         sink { (std::cout << ints)... };
    }
    

    Here you create a temporary object of type sink so that you use unpack the template arguments using list-initialization syntax.

    Last you could just use std::initializer_list itself:

    void foo(initializer_list const & ints) 
    {
    
    }
    

    Or std::vector in case if you need vector-like behavior inside foo(). If you use any of these, you have to use {} when calling the function as:

    f({1,2,3});
    

    That may not be ideal but I think with the advent of C++11 you will see such code very frequently!

提交回复
热议问题