読者です 読者をやめる 読者になる 読者になる

初期値が入力された要素数を取得する

C++

組み込み配列の、初期化子リストによる初期化は便利ですが、要素数より少ない数だけ初期化することが許可されているため、どこまで初期化されたかがわからないところが不便です。

#include <iostream>
#include <iterator>

int main()
{
    constexpr std::size_t size = 4;
    int data[size] = {1, 2, 3}; // 配列の要素数は4だが、初期値が入力されたのは3個
    for (std::size_t i = 0; i < size; ++i) {
        std::cout << data[i] << std::endl;
    }
}
1
2
3
0

その型の初期値が「使用しない値」や「無効値」として使用できるかはわからないので、こういった状況では、おとなしく可変長配列を使用するか、boost::optionalの配列にするのがいいでしょう。
しかし、それらの選択肢をとれない状況というのがあった場合のために、初期値が入力された数を取得する方法を紹介します。

#include <iostream>

#define NUMARGS(...)  (sizeof((int[]){__VA_ARGS__})/sizeof(int))
#define ARRAY(...) NUMARGS(__VA_ARGS__), {__VA_ARGS__}

struct X {
    int size;
    int data[4];
};

int main()
{
    X x = { ARRAY(1, 2, 3) };

    for (int i = 0; i < x.size; ++i) {
        std::cout << x.data[i] << std::endl;
    }
}
1
2
3

Xクラスのdataメンバ変数には、最大で4要素の値が入ります。sizeメンバ変数には、実際に初期値が入力された値が入ります。
xの初期化は、ARRAYマクロによって以下のように展開されます:

X x = { 3, {1, 2, 3} };

まず、配列の方は、単に可変引数マクロのパラメータを置いてるだけです。
要素数の方は、可変引数マクロのパラメータを、古典的なsizeofによる配列の要素数計算の方法によって計算しています。