enquanto eu lia, imaginei o cara da foto falando comigo... no final apenas consegui concordar com vc plenamente: duvidas e mais duvidas! :v

bom, pelo pouco que entendi, vc gostaria de ter um void *h e, dependendo do tipo escolhido, criar diferentes tipos de tabelas hash apontadas por h... bom, nao sei se estas funcoes fazem parte de alguma biblioteca, ao menos nao encontrei nada similar no meu sistema (mas eh um BSD, talvez esteja meio desatualizado)... enfim, supondo que nao eh algo padrao do sistema, eu particularmente usaria uma abordagem diferente... partindo do pressuposto que struct hash_table e hash_create() sao algo tipo:
- Código: Selecionar todos
// hash.h
#define HASHING_BY_BINTREE 1
#define HASHING_BY_SBBTREE 2
...
struct hash_table {
int type;
int size;
void *table;
int(*insert)(blablabla.);
...
};
// hash.c
#include <hash.h>
#include <sbbtree.h>
#include <bintree.h>
struct hash_table *hash_create(int type,int size)
{
struct hash_table *tmp = malloc(sizeof(...));
tmp->type = type;
tmp->size = size;
tmp->table = type==HASHING_BY_BINTREE ? bintree_create(blablabla) :
type==HASHING_BY_SBBTREE ? sbbtree_create(blablabla) : ...
tmp->insert = type==HASHING_BY_BINTREE ? bintree_insert :
type==HASHING_BY_SBBTREE ? sbbtree_insert : ...
...
ret tmp;
}
basicamente uma estrutura de dados que contem algo e uma funcao que popula essa estrutura de acordo com o tipo. isso seria uma interface entre as funcoes de hash e o resto da aplicacao, na pratica, a aplicacao ve hash.h e linka com hash.o (que pode ser uma libhash.so e conter e/ou apontar para bintree.so, sbbtree.so, etc). ateh acho que os type==algo ? ble : bla poderiam ser substituidos por algo tipo insert_by_type[type]. mas eu temo estar comecando a confudir C com verilog hahaha bom, eh um exemplo bem tosco e estou com preguica de digitar codigo longo... a interface ficaria bem simples:
- Código: Selecionar todos
#include <hash.h>
...
struct hash_table *h = hash_create(type, size);
h->insert(h,lots of things here);
...
h->delete(h);
em essencia: *h eh uma estrutura de dados que contem um determinado dado (a tabela hash, mas conforme o tipo) e contem os metodos que o manipulam... o tipo hash_type pode ser mudado arbitrariamente e isso tem seu lado bom e ruim... no caso, h->insert() eh relativamente rapido e eficiente: ele jah populou os metodos que manipulam essa estrutura quando foi criada, entao h->insert() eh realmente rapido, nao precisa ficar testando type==... e pode chamar as funcoes diretamente. divertido eh quando vc tem algo tipo h->event[event](h)... quer dizer, vc tem um array de ponteiros para funcao, que na pratica sao metodos diferentes para manipular diferentes situacoes geradas externamente... parece estranho, mas funciona feito um relogio!
claro, tem que ter toda uma verificacao e previsao de falhas: se vc chamar um tipo nao especificado, o que ocorre com h? provavelmente NULL... mas e se h for valido, porem aquele metodo nao existe? provavelmente h->insert = NULL... mas h->insert() falharia miseravelmente. entao talvez h->insert caia em uma funcao de tratamento de excessao para rodar sem crashar e produzir um diagnostico se h nao eh NULL. em essencia, se criar a estrutura sempre certa, nao deve falhar. oh claro, isso eh C: nao tem this, tem que referenciar h em h->delete(h), senao a funcao nao sabe exatamente o que fazer! bom, nao sei se era algo nesse sentido... independente disso, espero ter sido tao vago quanto gostaria e tao obscuro quanto o assunto merece! :v