void*初期化パラメーターと列挙型を受け取る単一の「コンストラクター」を定義できます。
enum StringCtor { SC_DEFAULT, SC_C_STR, SC_COPY };
String new_String(enum StringCtor type, const void *arg);
String s1 = new_String(SC_DEFAULT, 0);
String s2 = new_String(SC_C_STR, "hello");
String s3 = new_String(SC_COPY, &s2);
...
の代わりにを使用することもできますvoid *
。考え方は同じですva_*
が、文字列またはコピーであると想定される場合は、マクロを使用してパラメーターを抽出します。
APIに単一のコンストラクターの外観を持たせたいが、型の安全性を維持したい場合は、上記の手法を使用して実際のコンストラクター実装を作成し、インライン関数とプリプロセッサーのトリックを使用して単一のコンストラクターの外観を与えることができます。タイプセーフティ付き。
String new_StringImpl(enum StringCtor type, const void *arg);
static inline String new_StringImplDefault () {
return new_StringImpl(SC_DEFAULT, 0);
}
static inline String new_StringImplCstr (const char *s) {
return new_StringImpl(SC_C_STR, s);
}
static inline String new_StringImplCopy (String *s) {
return new_StringImpl(SC_COPY, s);
}
#define new_String_Paste(TYPE) new_String_ ## TYPE
#define new_String_SC_DEFAULT(ARG) new_StringImplDefault()
#define new_String_SC_C_STR(ARG) new_StringImplCstr(ARG)
#define new_String_SC_COPY(ARG) new_StringImplCopy(ARG)
#define new_String(TYPE, ...) new_String_Paste(TYPE)(__VA_ARGS__)
String s1 = new_String(SC_DEFAULT);
String s2 = new_String(SC_C_STR, "hello");
String s3 = new_String(SC_COPY, &s2);
可変個引数マクロで注意してSC_DEFAULT
ください。もう2番目のパラメーターは必要ありません。十分な最適化レベルでは、コードは単一の実装関数の呼び出しに変換され、コンパイル時の型安全性チェックの利点があります。したがって、コーディングを増やすことで、ライブラリのユーザーに、複数のコンストラクター関数のすべての型安全性を備えた単一のコンストラクターAPIの外観を与えることができます。