2010-06-12 3 views
2

stackoverflow에 대한 몇 가지 예제를 읽고 이전 질문 (1)에 대한 답변 중 일부를 따르면서 결국에는 "전략"이 생겼습니다.C++ 템플릿을 "모방"하는 C 전략은 무엇입니까?

나는이 왔어요 :

1).h 파일의 선언 섹션 되세요. 여기서는 데이터 구조와 액세스 인터페이스를 정의 할 것입니다. 예 :

MACROS 내부 인터페이스
/** 
* LIST DECLARATION. (DOUBLE LINKED LIST) 
*/ 
#define NM_TEMPLATE_DECLARE_LIST(type) \ 
typedef struct nm_list_elem_##type##_s { \ 
    type data; \ 
    struct nm_list_elem_##type##_s *next; \ 
    struct nm_list_elem_##type##_s *prev; \ 
} nm_list_elem_##type ; \ 
typedef struct nm_list_##type##_s { \ 
    unsigned int size; \ 
    nm_list_elem_##type *head; \ 
    nm_list_elem_##type *tail; \ 
    int (*cmp)(const type e1, const type e2); \ 
} nm_list_##type ; \ 
\ 
nm_list_##type *nm_list_new_##type##_(int (*cmp)(const type e1, \ 
    const type e2)); \ 
\ 
(...other functions ...) 

2) 랩 기능 :

/** 
* LIST INTERFACE 
*/ 
#define nm_list(type) \ 
    nm_list_##type 

#define nm_list_elem(type) \ 
    nm_list_elem_##type 

#define nm_list_new(type,cmp) \ 
    nm_list_new_##type##_(cmp) 

#define nm_list_delete(type, list, dst) \ 
    nm_list_delete_##type##_(list, dst) 

#define nm_list_ins_next(type,list, elem, data) \ 
    nm_list_ins_next_##type##_(list, elem, data) 

(...others...) 

3) 구현 기능 :들을 ​​사용하기 위해서는

/** 
* LIST FUNCTION DEFINITIONS 
*/ 
#define NM_TEMPLATE_DEFINE_LIST(type) \ 
nm_list_##type *nm_list_new_##type##_(int (*cmp)(const type e1, \ 
    const type e2)) \ 
{\ 
    nm_list_##type *list = NULL; \ 
    list = nm_alloc(sizeof(*list)); \ 
    list->size = 0; \ 
    list->head = NULL; \ 
    list->tail = NULL; \ 
    list->cmp = cmp; \ 
}\ 
void nm_list_delete_##type##_(nm_list_##type *list, \ 
    void (*destructor)(nm_list_elem_##type elem)) \ 
{ \ 
    type data; \ 
    while(nm_list_size(list)){ \ 
     data = nm_list_rem_##type(list, tail); \ 
     if(destructor){ \ 
      destructor(data); \ 
     } \ 
    } \ 
    nm_free(list); \ 
} \ 
(...others...) 

두 개의 파일을 만들어야합니다 (templates.c 및).). templates.c에서 내가하는 int, 복식 등, 생성 된 목록 뒤에 코드를 위해, NM_TEMPLATE_DEFINE_LIST(int), NM_TEMPLATE_DEFINE_LIST(double) 필요합니다 동안

templates.h에서 나는, NM_TEMPLATE_DECLARE_LIST(int), NM_TEMPLATE_DECLARE_LIST(double)해야합니다.

이 전략을 따르면 모든 "템플릿"선언을 두 파일로 유지해야하며 동시에 데이터 구조가 필요할 때마다 templates.h을 포함해야합니다. 매우 "중앙 집중화 된"솔루션입니다.

C + +에서 템플릿을 "모방"(어떤 시점에서)하기 위해 다른 전략을 알고 있습니까? 보다 분산 된 방식으로 작업을 유지하기 위해이 전략을 개선하는 방법을 알고 있으므로 두 파일이 필요하지 않습니다 : templates.ctemplates.h? 자신을 저장

+1

당신은 C의 위에 템플릿을 지원하는 언어를 구현할 수 있습니다;) 제가 적합하다고 생각하는 머리 위로 떨어져있는 대체 방법을 알지 못하지만 거의 모든 사람들이 이것을 수행하는 방법입니다 내 경험에 따라 템플릿이 필요한 패턴. – jer

+0

C++을 사용하는 것이 궁금 할 것 같습니까? –

+0

예, C++이 궁금합니다. –

답변

1

귀하의 예를 템플릿의 여러 가지 용도 중 하나가 아니라 - 일반 데이터 구조를 생성하는 단계를 포함한다. 이 예제는 템플리트를 강력하게 만드는 추론을 필요로하지 않습니다. 일반적인 데이터 구조를 만들 수있는 무언가를 요구하는 것은 실제로 C++ 템플릿과 동일한 것을 요구하는 것과 같은 질문이 아닙니다.

<tgmath.h>에 사용되는 구현 기술 중 일부는 유형 유추 기능을 제공하지만 C++ 템플릿보다 훨씬 약하고 이식성이 떨어집니다.

컨테이너의 구체적인 예는 void * 데이터가 포함 된 목록을 만든 다음 malloc과 free를 사용하여 데이터를 만들거나 목록에 함수 포인터 쌍을 제공하십시오. 가치를 창조하고 파괴하십시오. 값을 목록의 구성원으로 갖는 대신 클라이언트를 사용하여 데이터를 관리 할 수도 있습니다. 간접 참조를 저장하려면 데이터 멤버로 가변 길이 배열을 사용하십시오. C는 C++만큼 타입 안전하지 않기 때문에 void * 데이터를 갖는 것이 문제가되지 않습니다.

매크로를 사용하여 정교한 코드 생성을 수행 할 수 있지만 코드 생성을위한 다른 도구도 있습니다. 개인적으로 나는 코드 생성을 위해 XSLT를 사용하는 것을 좋아하지만, 빌드 과정에서 완전히 C가 아닌 부분을 가지고있다.

1

몇 가지 문제와 매크로 queue(3) 세트 기존 사용 - 시도 및 테스트, 커널 소스에서 사용을 등

2

아마이 일을 인정하지만 내가 필요로 할 때 다음과 같이 과거에 C 토지 용기, 나는 특수 파일 한 쌍으로 '플릿 큐 클래스'를 썼다 "플릿"안 :

파일 MyQueue.include_h :

/** NOTE: THIS IS NOT a REAL .h FILE, it only looks like one! Don't #include it! */ 
struct MyQueueClass 
{ 
    void init_queue(MyQueueClass * q); 
    void push_back(MyQueueClass * q, MyQueueClassItem * item); 

    [....All the other standard queue header declarations would go here....] 

    MyQueueClassItem * _head; 
    MyQueueClassItem * _tail; 
    int _size; 
}; 

파일 MyQueue.include_c : 다음

/** NOTE: THIS IS NOT A REAL .c FILE, it only looks like one! Don't compile directly! */ 
void init_queue(MyQueueClass * q) 
{ 
    q->_size = 0; 
    q->_head = q->_tail = NULL; 
} 

void push_back(MyQueueClass * q, MyQueueClassItem * item) 
{ 
    if (q->_head == NULL) q->_head = q->_tail = item; 
    else 
    { 
     q->_tail->_next = item; 
     item->_prev = q->_tail; 
     q->_tail = item; 
    } 
    q->_size++; 
} 

[....All the other standard queue function bodies would go here....] 

, 내가 특정 항목 - 일반을 사용하여 내 대기열 "템플릿"을 "인스턴스화"하고 싶어 할 때마다

내 진짜가 .c 파일 중 하나에서
#define MyQueueClass struct SomeSpecificQueueType 
#define MyQueueClassItem struct SomeSpecificQueueTypeItem 
# include "MyQueue.include_h" 
#undef MyQueueClassItem 
#undef MyQueueClass 

(그것은 아무튼 : 내 진짜 .H 파일 중 하나에서

: 전자, 나는 실제가 .c 및 .H 파일에 이런 식으로 뭔가를 넣어 것

#define MyQueueClass struct SomeSpecificQueueType 
#define MyQueueClassItem struct SomeSpecificQueueTypeItem 
# include "MyQueue.include_c" 
#undef MyQueueClass 
#undef MyQueueClassItem 

.... 넣거나, 전체 "템플릿 정의"를 요구하지 않고 가난한 사람의 템플릿 확장으로 C 전 처리기 행위는, 거대한 #DEFINE에서 만들 수 '는 t는 하나)하는 문제 성명서.

+2

하나의 파일에 여러 유형의 값을 보유하는 두 개의 대기열을 선언 할 수 없습니다. 함수 이름이 충돌합니다. –

관련 문제