Есть ли способ получить эффект шаблона в C? - PullRequest
3 голосов
/ 24 июня 2011

Я разработал C dll, содержащий простые функции списка ссылок, но все они определены в типе int, то есть когда пользователь создает список ссылок, используя мою библиотеку, он может создавать только список целых чисел. Так что, если бы я мог сделать что-то (кроме void *), чтобы позволить пользователю создать список произвольных типов данных, таких как char, float или даже пользователь, определяющий struct? Это тоже без перекомпиляции.

спасибо.

Ответы [ 7 ]

3 голосов
/ 24 июня 2011

Использование макросов - это достойный подход к шаблонизации определений, то есть генерация любого количества определений на основе шаблона. Вот пример - но он ужасен как ад.

#include <stdlib.h>

#define template_struct_A(T1,T2) struct A_ ## T1 ## _ ## T2 { \
    T1 a; \
    T2 b; \
}
#define struct_A(T1,T2) struct A_ ## T1 ## _ ## T2

struct C { const char*s; };

typedef const char* pchar;
template_struct_A(int, pchar); // explicit instantiation of struct A<int, pchar>

int main() {
    struct X { struct C x; } x;
    struct_A(int, pchar) o1; // struct A<int, const char*> o1
    o1.a = 1;
    o1.b = "hello";

    struct_A(int, pchar) o2; // struct A<int, const char*> o2
    o2.a = o1.a * 2;
    o2.b = "world";

    typedef struct_A(int, pchar)* pAInt;
    typedef struct C structC;
    template_struct_A(pAInt, structC) o3; // struct A<struct A<int, const char*>, struct C> o3
    o3.a = &o2;
    o3.b.s =  "hi";

    printf ("o1.a = %d, o1.b = %s, o2.a = %d, o2.b = %s, o3.b.s = %s\n", o1.a, o1.b, o2.a, o2.b, o3.b.s);
}
1 голос
/ 24 июня 2011

Я согласен с другими ответами, что void * - единственный путь. Но вы можете сжать более динамическое поведение без перекомпиляции, если добавите параметр размера, который указывает, на сколько байтов указывает void *.

void *shift(list *plist, unsigned size);
void unshift(list *plist, void *item, unsigned size);

Тогда вы можете скрыть размер с помощью макросов.

#define Cshift(L)   shift(L,sizeof(char))
#define Cunshift(L,I) unshift(L,I,sizeof(char))
1 голос
/ 24 июня 2011

Поддержка языков / компиляторов

Примеры

1 голос
/ 24 июня 2011

Единственный вариант, кроме void *, ну ничего.

Единственный вариант - void *, это то, что я говорю.

void * является единственным универсальным типом в C; и в некоторой степени также единственная общая степень в C ++; как и то, что вы бы назвали динамическими языками.

Конечно, если вы чувствуете себя особенно сумасшедшим, вы можете перенастроить свою внутреннюю структуру, чтобы ссылки связанного списка включали объединение, и иметь ряд функций, названных

add_<type>_to_list(); // <type> = char, int, float…

Но это вряд ли даст удовлетворительные результаты.

0 голосов
/ 24 июня 2011

Вы можете существенно переписать C ++ на C, в зависимости от того, какой уровень детализации вам необходим. Вы можете начать с создания типа данных связанного списка struct * для некоторой структуры-оболочки, которая сама может содержать идентификатор типа и пустой указатель на фактические данные. Вы можете написать свой собственный vtable, чтобы учесть полиморфизм, и вы могли бы добавить подсчет ссылок и управление памятью ... ничего из этого не волшебство, поэтому, если вам действительно нужна такая общность, вы, безусловно, можете написать все это на C. Или просто используйте C ++: -)

0 голосов
/ 24 июня 2011

Вы можете использовать макросы. Например, вы можете создать разные типы узлов списка с разными типами data членов и убедиться, что все они имеют элементы next и prev. Затем просто используйте макросы для всех операций со списком (например, добавление, вставка, удаление), так как они не заботятся о сохраняемом типе.

Конечно, макросы не так безопасны как шаблоны и считаются «плохим стилем». Но эй, мы в Си, кто боится макросов в Си? И void* тоже не такой безопасный.

0 голосов
/ 24 июня 2011

Нет способа сделать это во время выполнения без void *.Но есть способ сделать это без отдельно скомпилированного кода: все операции могут быть # define.

http://www.freebsd.org/cgi/cvsweb.cgi/src/sys/sys/queue.h?rev=1.75;content-type=text%2Fx-cvsweb-markup

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...