Variable number of parameters in function in C++

前端 未结 8 1833
借酒劲吻你
借酒劲吻你 2020-12-07 20:32

How I can have variable number of parameters in my function in C++.

Analog in C#:

public void Foo(params int[] a) {
    for (int i = 0; i < a.Leng         


        
相关标签:
8条回答
  • 2020-12-07 21:11

    I do mine like this in c++ builder xe.xx:

    String s[] = {"hello ", " unli", " param", " test"};
    String ret = BuildList(s, 4);
    
    String BuildList(String s[], int count)
    {
        for(int i = 0; i < count; i++)
        {
            //.... loop here up to last s[i] item ... 
        }
    }
    
    0 讨论(0)
  • 2020-12-07 21:12

    In C++11 and later you can also use initializer lists.

    int sum(const initializer_list<int> &il)
    {
        int nSum = 0;
        for (auto x: il) 
            nSum += x;
        return nsum;
    }
    
    cout << sum( { 3, 4, 6, 9 } );
    
    0 讨论(0)
  • 2020-12-07 21:14

    Aside from the other answers, if you're just trying to pass an array of integers, why not:

    void func(const std::vector<int>& p)
    {
        // ...
    }
    
    std::vector<int> params;
    params.push_back(1);
    params.push_back(2);
    params.push_back(3);
    
    func(params);
    

    You can't call it in parameter, form, though. You'd have to use any of the variadic function listed in your answers. C++0x will allow variadic templates, which will make it type-safe, but for now it's basically memory and casting.

    You could emulate some sort of variadic parameter->vector thing:

    // would also want to allow specifying the allocator, for completeness
    template <typename T> 
    std::vector<T> gen_vec(void)
    {
        std::vector<T> result(0);
        return result;
    }
    
    template <typename T> 
    std::vector<T> gen_vec(T a1)
    {
        std::vector<T> result(1);
    
        result.push_back(a1);
    
        return result;
    }
    
    template <typename T> 
    std::vector<T> gen_vec(T a1, T a2)
    {
        std::vector<T> result(1);
    
        result.push_back(a1);
        result.push_back(a2);
    
        return result;
    }
    
    template <typename T> 
    std::vector<T> gen_vec(T a1, T a2, T a3)
    {
        std::vector<T> result(1);
    
        result.push_back(a1);
        result.push_back(a2);
        result.push_back(a3);
    
        return result;
    }
    
    // and so on, boost stops at nine by default for their variadic templates
    

    Usage:

    func(gen_vec(1,2,3));
    
    0 讨论(0)
  • 2020-12-07 21:15

    GManNickG and Christoph answers are good, but variadic functions allow you push in the ... parameter whatever you want, not only integers. If you will want in the future, to push many variables and values of different types into a function without using variadic function, because it is too difficult or too complicated for you, or you don't like the way to use it or you don't want to include the required headers to use it, then you always can use void** parameter.

    For example, Stephan202 posted:

    double average(int count, ...)
    {
        va_list ap;
        int j;
        double tot = 0;
        va_start(ap, count); //Requires the last fixed parameter (to get the address)
        for(j=0; j<count; j++)
            tot+=va_arg(ap, double); //Requires the type to cast to. Increments ap to the next argument.
        va_end(ap);
        return tot/count;
    }
    

    this can be also written as:

    double average(int count, void** params)
    {
        int j;
        double tot = 0;
        for (j=0; j<count; j++)
           tot+=*(double*)params[j];
        return tot/count;
    }
    

    Now use it like this way:

    int _tmain(int argc, _TCHAR* argv[])
    {
        void** params = new void*[3];
        double p1 = 1, p2 = 2, p3 = 3;
        params[0] = &p1;
        params[1] = &p2;
        params[2] = &p3;
        printf("Average is: %g\n", average(3, params));
        system("pause");
        return 0;
    }
    

    for full code:

    #include "stdafx"
    #include <process.h>
    
    double average(int count, void** params)
    {
        int j;
        double tot = 0;
        for (j=0; j<count; j++)
            tot+=*(double*)params[j];
        return tot/count;
    }
    
    int _tmain(int argc, _TCHAR* argv[])
    {
        void** params = new void*[3];
        double p1 = 1, p2 = 2, p3 = 3;
        params[0] = &p1;
        params[1] = &p2;
        params[2] = &p3;
        printf("Average is: %g\n", average(3, params));
        system("pause");
        return 0;
     }
    

    OUTPUT:

    Average is: 2

    Press any key to continue . . .

    0 讨论(0)
  • 2020-12-07 21:20

    The real C++ solution is variadic templates. You'll need a fairly recent compiler and enable C++11 support if needed.

    Two ways to handle the "do the same thing with all function arguments" problem: recursively, and with an ugly (but very very Standards compliant) solution.

    The recursive solution looks somewhat like this:

    template<typename... ArgTypes>
    void print(ArgTypes... args);
    template<typename T, typename... ArgTypes>
    void print(T t, ArgTypes... args)
    {
      std::cout << t;
      print(args...);
    }
    template<> void print() {} // end recursion
    

    It generates one symbol for each collection of arguments, and then one for each step into the recursion. This is suboptimal to say the least, so the awesome C++ people here at SO thought of a great trick abusing the side effect of a list initialization:

    struct expand_type {
      template<typename... T>
      expand_type(T&&...) {}
    };
    template<typename... ArgTypes>
    void print(ArgTypes... args)
    { 
      expand_type{ 0, (std::cout << args, 0)... };
    }
    

    Code isn't generated for a million slightly different template instantiations, and as a bonus, you get preserved order of you function arguments. See the other answer for the nitty gritty details of this solution.

    0 讨论(0)
  • 2020-12-07 21:20

    See Variadic functions in C, Objective-C, C++, and D

    You need to include stdarg.h and then use va_list, va_start, va_arg and va_end, as the example in the Wikipedia article shows. It's a bit more cumbersome than in Java or C#, because C and C++ have only limited built-in support for varargs.

    0 讨论(0)
提交回复
热议问题