Ich habe eine Idee.
#define C_ASSERT(expr) extern char CAssertExtern[(expr)?1:-1]
#define NUM_ARGS__(X, \
N64,N63,N62,N61,N60, \
N59,N58,N57,N56,N55,N54,N53,N52,N51,N50, \
N49,N48,N47,N46,N45,N44,N43,N42,N41,N40, \
N39,N38,N37,N36,N35,N34,N33,N32,N31,N30, \
N29,N28,N27,N26,N25,N24,N23,N22,N21,N20, \
N19,N18,N17,N16,N15,N14,N13,N12,N11,N10, \
N09,N08,N07,N06,N05,N04,N03,N02,N01, N, ...) N
#define NUM_ARGS(...) \
NUM_ARGS__(0, __VA_ARGS__, \
64,63,62,61,60, \
59,58,57,56,55,54,53,52,51,50, \
49,48,47,46,45,44,43,42,41,40, \
39,38,37,36,35,34,33,32,31,30, \
29,28,27,26,25,24,23,22,21,20, \
19,18,17,16,15,14,13,12,11,10, \
9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
#define DECL_INIT_ARRAYN(TYPE, NAME, COUNT, N, ...) \
C_ASSERT(COUNT == N); \
TYPE NAME[COUNT] = { __VA_ARGS__ }
#define DECL_INIT_ARRAY(TYPE, NAME, COUNT, ...) \
DECL_INIT_ARRAYN(TYPE, NAME, COUNT, NUM_ARGS(__VA_ARGS__), __VA_ARGS__)
DECL_INIT_ARRAY(const int, array3_3, 3, 1, 2, 3);
int main(void)
{
DECL_INIT_ARRAY(const int, array5_4, 5, 1, 2, 3, 4);
DECL_INIT_ARRAY(const int, array5_6, 5, 1, 2, 3, 4, 5, 6);
return 0;
}
Output (ideone):
prog.c: In function ‘main’:
prog.c:33:3: error: size of array ‘CAssertExtern’ is negative
prog.c:34:3: error: size of array ‘CAssertExtern’ is negative
prog.c:34:3: error: excess elements in array initializer [-Werror]
prog.c:34:3: error: (near initialization for ‘array5_6’) [-Werror]
prog.c:34:3: error: unused variable ‘array5_6’ [-Werror=unused-variable]
prog.c:33:3: error: unused variable ‘array5_4’ [-Werror=unused-variable]
prog.c:34:3: error: unused variable ‘CAssertExtern’ [-Werror=unused-variable]
cc1: all warnings being treated as errors
UPD: Die OP wurde gefunden eine kürzere C++ 11-Lösung an, die auf der gleichen Idee __VA_ARGS__
Verwendung und eine statische/Kompilierzeit-Assertion:
#include <tuple>
#define DECL_INIT_ARRAY(TYPE, NAME, COUNT, ...) \
static_assert(COUNT == \
std::tuple_size<decltype(std::make_tuple(__VA_ARGS__))>::value, \
"Array " #NAME " should have exactly " #COUNT " initializers"); \
TYPE NAME[COUNT] = { __VA_ARGS__ }
DECL_INIT_ARRAY(const int, array3_3, 3, 1, 2, 3);
int main(void)
{
DECL_INIT_ARRAY(const int, array5_4, 5, 1, 2, 3, 4);
DECL_INIT_ARRAY(const int, array5_6, 5, 1, 2, 3, 4, 5, 6);
return 0;
}
Ausgabe (ideone):
prog.cpp: In function ‘int main()’:
prog.cpp:13:3: error: static assertion failed: Array array5_4 should have exactly 5 initializers
prog.cpp:14:3: error: static assertion failed: Array array5_6 should have exactly 5 initializers
prog.cpp:14:3: error: too many initializers for ‘const int [5]’
prog.cpp:13:3: warning: unused variable ‘array5_4’ [-Wunused-variable]
prog.cpp:14:3: warning: unused variable ‘array5_6’ [-Wunused-variable]
Ich bin mir nicht sicher über eine Warnung, aber jeder Compiler, der einen Fehler für diesen gab, wäre ein nichtkonformer Compiler. Ich kann mir nicht vorstellen, dass ein Compilerhersteller eine solche Option zu seinem Produkt hinzufügt, dafür sind statische Analysetools gedacht. – Jon
GCC hat '-Wissing-field-initializers', aber es funktioniert nur für andere Aggregate, nicht für Arrays, wahrscheinlich weil die meisten Leute nicht wollen, dass es für Arrays warnt. Können Sie nicht Komponententests verwenden, um sicherzustellen, dass das Array die richtigen Werte enthält und die nachfolgenden Elemente nicht initialisiert wurden? –
@ JonathanWakely Im Gegenzug ist 'std :: array' ein Aggregat! (Ich mag diese Warnung im Gegensatz dazu nicht.) –