TheFrog
TheFrog

Reputation: 56

Variable-length argument list in C++ object

Good evening,

I'm writing some classes, and I have a case where I would like a class method to take a variable number of arguments. I had issues getting this to compile, so I set up a very simple test case:

TestObject.h:

#include <ostream>
#include <stdarg.h>

class TestObject
{
    public:
    void test(int intCount, ...);
};

and TestObject.cpp:

#include "TestObject.h"

void TestObject::test(int intCount, ...)
{
    va_list objList;
    va_start objStart(objList, intCount);
    int numArgs = va_arg(objList, int);
}

Finally, main.cpp:

#include<stdarg.h>

int maxof(int n_args, ...)
{
    va_list ap;
    va_start(ap, n_args);
    int max = va_arg(ap, int);
    for (int i = 2; i <= n_args; i++) {
        int a = va_arg(ap, int);
        if (a > max) max = a;
    }
    va_end(ap);
    return max;
}

int main(int argc, char** argv)
{
    int max = maxof(3, 1, 3, 2);

    return 0;
}

main.cpp will compile just fine on its own, so I've narrowed it down to the case where the variable-length argument is in a class. When I add the classes to the project and try to compile, the build fails with the error C2065: '__crt_va_start': undeclared identifier. I'm building in Visual Studio 2015.

I'm aware that C++ has variadic templates, but whenever I get into template classes, I always seem to have to convert the class and usually related classes into header-only files and I'd like to avoid that. What I would probably do alternatively is just take a vector argument of some generic type.

Can someone tell me if I'm missing something here? Should I be able to compile and run a class method that has a variable-length argument in C++, or is this just something that's not supported?

Thanks!

Upvotes: 0

Views: 668

Answers (1)

ixSci
ixSci

Reputation: 13708

Using a modern compiler you should not fall back to this old-style ellipsis syntax. For your purposes std::initializer_list is pretty good an alternative. Look how simple the code with it is:

#include <limits>

int maxof(std::initializer_list<int> args)
{
    int max = std::numeric_limits<int>::min();
    for(auto arg : args)
        if(arg > max) max = arg;
    return max;
}

int main(int argc, char** argv)
{
    int max = maxof({3, 7, 1, 3, 2, 5});
    return 0;
}

Upvotes: 2

Related Questions