可変個引数

C言語で,可変個の引数をとる関数を定義するときは,

void test_varargs( const char* fmt, ... )
{
    va_list args;
    va_start(args, fmt);
    int i = 0;
    while(fmt[i] != '\0'){
        switch(fmt[i]){
            case 'd':
                {
                    int val = va_arg(args, int);
                    printf("%d\n", val);
                    break;
                }
            case 'f':
                {
                    double val = va_arg(args, double);
                    printf("%f\n", val);
                    break;
                }
            case 'c':
                {
                    char val = va_arg(args, char);
                    printf("%c\n", val);
                    break;
                }
        }
        ++i;
    }
    va_end(args);
}

としていました.
C#で実現するには,(以下,MSDNより抜粋

// cs_params.cs
using System;
public class MyClass 
{

    public static void UseParams(params int list) 
    {
        for (int i = 0 ; i < list.Length; i++)
        {
            Console.WriteLine(list[i]);
        }
        Console.WriteLine();
    }

    public static void UseParams2(params object list) 
    {
        for (int i = 0 ; i < list.Length; i++)
        {
            Console.WriteLine(list[i]);
        }
        Console.WriteLine();
    }

    static void Main() 
    {
        UseParams(1, 2, 3);
        UseParams2(1, 'a', "test"); 

        // An array of objects can also be passed, as long as
        // the array type matches the method being called.
        int[] myarray = new int[3] {10,11,12};
        UseParams(myarray);
    }
}

のように,paramsキーワードを使用します.
参考URIparams (C# リファレンス)


ならば,C++/CLIではどうやるのだろうと思い,調べてみたところ,

using namespace System;
double func( ... array<double>^ args )
{
    double sum = 0.0;
    for(int i=0 ; i<args->Length ; ++i){
        sum += args[i];
    }
    return sum;
}

のようにすれば実現可能であることがわかりました.
参考URIVariable Argument Lists (...) (C++/CLI)


何でこんなことを調べていたのかというと,KrdLibのMatrixクラスに値を設定するとき,

Matrix m = new Matrix(3, 3);
m[0, 0] = 4; m[0, 1] = 1; m[0, 2] = -4;
m[1, 0] = 3; m[1, 1] = 4; m[1, 2] = -6;
m[2, 0] = 2; m[2, 1] = 1; m[2, 2] = -2;

のようにするのはめんどくさいので,

Matrix m = Matrix.Create( Matrix.Row(4, 1, -4),
                          Matrix.Row(3, 4, -6),
                          Matrix.Row(2, 1, -2) );
// ↑CreateとRowは,可変個の引数を扱う必要がある

のように設定したいなぁ...,と思ったからです.
で,やり方がわかったため,早速実装しました.

ref class Matrix {
//...(ほげほげ)
public:
    static RowVector^ Row( ... array<double>^ args )
    {
        RowVector^ rv = gcnew RowVector(args->Length);
        for(int i=0 ; i<args->Length ; ++i){
            rv[i] = args[i];
        }
        return rv;
    };
    
    static Matrix^ Create( ... array<RowVector^>^ args )
    {
        Matrix^ m = gcnew Matrix(args->Length, args[0]->Size);
        for(int r=0 ; r<args->Length ; ++r){
            m[r] = args[r];
        }
        return m;
    }
    
//...(ほげほげ)
};

よしよし.(`ω´)