I know how to create a function with variable argument list, but how do you create one when the argument type is unknown, something like MyPrintf(...) ? From what I've read CLR/C++ only supports known argument types, such as int,
MyPrintf("...array<Int32>^ arr)

and the calling function

int main()
   MyPrintf("One", "two", 3,4);

Recommended Answers

All 5 Replies

If the type is unknown, try using Object^. Provided you're working with CLI types, they're all derived from Object.

Hi AD, maybe something like this:

// vargs.cpp : main project file.

#include "stdafx.h"

using namespace System;

static void UseVariableParameters(... array<Object^>^ list)
    for ( int i = 0 ; i < list->Length ; i++ )

static void DemonstrateVariableParameters()
    UseVariableParameters("Help",2,3,4,5, '%d');

int main(array<System::String ^> ^args)
    return 0;


In ANSI-C++, you can use the vargs mechanism. I have not tried this in MS-Managed C++. First, #include <stdarg.h> at the start of your source file that will be using this capability. Actually first, think, "Do I really need to do this, or am I just being lazy in my programming?" If you really need to do this, proceed.

<stdarg.h> is a C include file that includes the struct, functions and macros needed for this. va_list is a type that is used to keep track of the extra arguments to the function. va_start(x,y) tells the compiler to start reading arguments using the va_list x, starting after the argument y. va_arg reads the next argument and also indicates what type it should be. Doing a static_cast here is often a good idea. When you are done reading the extra arguments, call va_end(x) to clean up things.

Here is an ANSI-C++ example using this system.

/* vatest.cpp
 * by David Nuttall
 * Test the methods for getting multiple parameters of different types.

#include <cstdarg>
#include <iostream>

int vafunc(const char *sPattern, ...)
    int iIndex;
    va_list args;

    va_start(args, sPattern);   // start reading the arguments in args, starting after sPattern
    for (iIndex = 0; sPattern[iIndex] != '\0'; ++iIndex)
    switch (sPattern[iIndex])
        case 'b':
        // print a boolean
        std::cout << std::boolalpha << static_cast<bool>(va_arg(args, int)) << ' '; // bool gets promoted to int, then back to bool.
        case 'c':
        // print a character
        std::cout << static_cast<char>(va_arg(args, int)) << ' '; // char gets promoted to int, then back to char.
        case 'd':
        // print a double
        std::cout << static_cast<double>(va_arg(args, double)) << ' ';
        case 'f':
        // print a float (single)
        std::cout << static_cast<float>(va_arg(args, double)) << ' ';    // float get promoted to double, then back to float.
        case 'i':
        // print an integer
        std::cout << static_cast<int>(va_arg(args, int)) << ' ';
        case 'l':
        // print a long integer
        std::cout << static_cast<long>(va_arg(args, long)) << ' ';
        case 's':
        // print a string
        std::cout << static_cast<char *>(va_arg(args, char *)) << ' ';
        // Flags
        case 'F':
        // Fixed point notation
        std::cout << std::fixed;
        case 'S':
        // Scienfic notation
        std::cout << std::scientific;
        case 'X':
        // Reset notation
        case 'H':
        // Hexidecimal notation
        std::cout << std::hex;
        case 'O':
        // Octal notation
        std::cout << std::oct;
        case 'D':
        // Decimal notation
        std::cout << std::dec;
        // Do not know what to do with this!
        std::cerr << "I do not know what to do with " << sPattern[iIndex] << '.' << std::endl;
        return 1;
    } // for
    std::cout << std::endl;
    return 0;

int main(void)
    vafunc("scHiDb", "String", 'c', 555, 16);
    vafunc("dSfFdl", 18e100, 1963.22f, 160.442, 10000L);

    return 0;

In ANSI-C++, you can use the vargs mechanism. I have not tried this in MS-Managed C++.

Thanks for the suggestion, but CLR/C++ is NOT ANSI C++, and it doesn't support vargs.

How about using Templates? Or using the Object data type since it's polymorphic anyway?

public void Print(...array<Object^> ^objects)
    foreach (Object^ o in objects)
        Console::Write(o + " ");

Object Datatype can accept any other type whether it is known or not.. For example, a class. Of course for the class to print nicely it should overload tostring..

Can use it like: Print(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, "1", "2", "3", "4", "5", SomeClassThatOverloadsToString, SomeClass2);

Then there is the template solution which is variadic but only accepts one type unless you specify Object.

using namespace System;
using namespace System::Collections::Generic;

template <typename T>
public ref class CustomType sealed
        List<T> TypeData;

        CustomType() {}
        CustomType(...array<T^> ^Types)            //Basically Variadic Templates.. As good as it gets for MS2010..
            for each (T^ t in Types)
        ~CustomType() {}

        virtual String^ ToString() override
            String^ Str;
            if (this->size() != 0)
                Str = "[";
                for (int I = 0; I < this->size() - 1; I++)
                    Str += TypeData[I];
                    Str += ", ";
                Str += TypeData[this->size() - 1];
                Str += "]";
                Str += "[]";
            return Str;

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, learning, and sharing knowledge.