2010-05-23 49 views
2

如何處理echo_tpl的功能 intstring的參數,然後將其打印出來?在C中使用模板函數的最短例子?

+0

你確定你不是指C++嗎? AFAIK C沒有模板。 – 2010-05-23 11:44:19

+0

最近相關的問題:http://stackoverflow.com/questions/2873850/is-there-a-equivalent-in-c-for-c-templates – dmckee 2010-05-23 11:55:40

回答

-1
template <typename T> 
void echo_tpl(const T& t) { std::cout << t; } 

編輯:我沒有發現c標籤。上述答案只適用於C++。

+0

這不是C++嗎? – httpinterpret 2010-05-23 11:45:38

+0

是的。這就是爲什麼我刪除了我的類似答案... – 2010-05-23 11:47:17

8

C沒有模板。我認爲你能做的最好的事情就是使用聯盟或者讓這些職能有不同的名字。具有不同的名稱的後者的方法是這樣做(例如fabsfabsffabsl,也heavily used由OpenGL的它也考慮了這樣的事實C不能過載功能)

void echo_tpl_s(char const *string) { /* ... */ } 
void echo_tpl_i(int number) { /* ... */ } 

int main(void) { 
    echo_tpl_s("Hello world"); 
    echo_tpl_i(42); 
} 

如果存在的準標準方法很多共同的代碼,你可以決定在不同的功能

void echo_tpl_s(char const *string) { 
    prepare_output_device(); 
    printf("%s", string); 
    unprepare_output_device(); 
} 

void echo_tpl_i(int number) { 
    prepare_output_device(); 
    printf("%d", number); 
    unprepare_output_device(); 
} 

還是要因素出來,你可以採取工會方式,這將有日e函數名稱是相同的,但用元信息放大參數類型。如果你想在一些地方保存的值,然後執行打印功能,而無需關心你傳遞給它什麼樣的價值型

enum Type { 
    Number, 
    String 
}; 

struct Value { 
    enum Type type; 
    union { 
    int number; 
    char const *string; 
    } u; 
}; 

void echo_tpl(struct Value value) { 
    switch(value.type) { 
    case Number: printf("%d", value.u.number); break; 
    case String: printf("%s", value.u.string); break; 
    } 
} 

int main(void) { 
    echo_tpl((struct Value) { 
    .type = String, 
    .u.string = "Hello world" 
    }); 
} 

的結合的方式尤其是非常適合。在C89,你會需要單獨創造的價值,因爲它不具有複合文字

int main(void) { 
    struct Value value; 
    value.type = String; 
    value.u.string = "Hello world"; 
    echo_tpl(value); 
} 

它來創建該功能是個好主意,但

struct Value stringval(char const *string) { 
    struct Value value; 
    value.type = String; 
    value.u.string = string; 
    return value; 
} 

struct Value numberval(int number) { 
    struct Value value; 
    value.type = Number; 
    value.u.number = number; 
    return value; 
} 

int main(void) { 
    echo_tpl(stringval("Hello world!")); 
} 

一些編譯器可以提供寫這些東西的擴展。例如Clang在C.

void echo_tpl(int value) __attribute__((overloadable)) { 
    printf("%d", value); 
} 

void echo_tpl(char const *value) __attribute__((overloadable)) { 
    printf("%s", value); 
} 

提供function overloading這解決了該函數的調用側不依賴於類型。在定義方面,您仍然需要編寫兩次代碼。這主要是因爲(如另一個答案所解釋的)C沒有類型通用的輸出函數。當然,如果你使用這個特性,你的代碼將變得不可移植。

+0

+1,我打算建議使用聯盟。 – 2010-05-23 12:19:34

+0

對於64位機器,這種方法可以嗎? – 2010-05-23 12:32:51

+0

@加強這兩種技術將適用於64位機器。一個工會的成員不需要有相同的規模。 – 2010-05-23 12:37:04

4

將模板轉換爲C的傳統方法是使用預處理器。我會做這樣的事情:

// this creates each template "instance" 
#define ECHO_TPL_IMPLEMENT(t) void echo_tpl_##t(t param){\ 
/* this is where you write your function that uses param */ \ 
} 

// this calls the specific template instance 
#define ECHO_TPL(t, val) echo_tpl_##t(val) 

// as i wrote it, the function only accepts a 1 word parameter type 
// so for simplicity, i'm defining char* to be string 
typedef char *string; 

// i implement the function for the types int and string 
ECHO_TPL_IMPLEMENT(int)  // creates echo_tpl_int 
ECHO_TPL_IMPLEMENT(string) // creates echo_tpl_string 

main() 
{ 
    // then i just call them and let the preprocessor handle it 
    ECHO_TPL(string, "meep"); // will call echo_tpl_string 
    ECHO_TPL(int, 10);   // will call echo_tpl_int 
} 

這是怎麼了原來的C++編譯器處理的模板,只是他們(現在仍然如此,這一天)更復雜的類型混淆規則,在這裏我只是假設類型1單詞,如果他們不是,你將不得不typedef他們。

編輯:請注意,我將該函數留空。這實際上是你如何在C中編寫「模板化函數」,但是我不能真正寫出你問的參數,因爲C沒有寫入api的類型無關的文件。printfwrite需要有關實際類型的信息(通過%d%s以及分別寫入的字節長度),我們沒有這些信息。

另請注意,這也適用於C++。您不能使用C api從模板寫入文件,您只能真正使用cout(或升壓格式替代或類似的東西)。你將不得不考慮你想用實際功能做什麼。

+0

呃你是對的,它遲到:( – Blindy 2010-05-23 12:33:41

0

儘管如此,值得補充的是,從C11標準開始,現在C使用_Generic表達式對超載進行了一些非常有限的支持,該表達式在編譯時根據輸入類型選擇正確的結果表達式。什麼樣的模板,但他們能回答這個古老的問題是這樣的:

#define echo_tpl(X) _Generic((X), int: echo_tpl_i, \ 
           char *: echo_tpl_s)(X) 

void echo_tpl_s(char const *string) { /* ... */ } 
void echo_tpl_i(int number) { /* ... */ } 

int main(void) { 
    echo_tpl("Hello world"); 
    echo_tpl(42); 
} 

你還有你的C99將定義使用不同的名稱的功能實現,但你可以定義與C++的宏 - ISH名稱在每個使用點處插入_Generic表達式,以便爲該調用站點選擇正確的版本,而不會讓功能用戶考慮參數類型。

C標準似乎需要永遠的完全採用,我不知道哪些編譯器實現了這個功能,但是如果有更多的人去使用它,它將會越來越普及!