Cでは汎用コンテナを使用したい場合は、一般的なアプローチの1つはvoid*
です。カスタムの割り当て解除関数は汎用コンテナとの互換性を考慮する必要がありますか?
struct Foo {...};
Foo *Foo_Allocate(...);
void Foo_Deallocate(const Foo*);
int main(void)
{
/* Let's assume that when you create the list you have to
specify the deallocator of the type you want to hold */
List *list = List_Allocate(Foo_Deallocate);
/* Here we allocate a new Foo and push it into the list.
The list now has possession of the pointer. */
List_PushBack(list, Foo_Allocate());
/* When we deallocate the list, it will also deallocate all the
items we inserted, using the deallocator specified at the beginning */
List_Deallocate(list);
}
しかし、最も可能性の高いデアロケータ関数の型はvoid*
typedef void (*List_FnItemDeallocator)(const void*);
Foo_Deallocate
がconst Foo*
で、const void*
ではありません。署名が一致しなくても関数を渡すのはまだ安全ですか?おそらくそうではないでしょう。
もしそれができないのであれば、すべてのデアロケータ関数は関連する型へのポインタの代わりにconst void*
を取ることをお勧めします。それらは汎用コンテナと互換性がありますか?
このモデルは、不満足なアシンメトリを提供します。クライアントは 'Foo'の割り当てを担当しますが、コンテナはそれらの割り当てを解除します。 –
@OliCharlesworthこれは単純な例です。 'List_Allocate'がデアロケータだけでなくコピー/クローン機能についても尋ねるケースを想像してみてください。また、要素をコピーし、その引数を保持しない 'List_CopyBack'のような関数を提供するかもしれません。誰がこれらのオブジェクトを解放するのは誰の責任ですか? –