36

さまざまな種類の数値配列を処理するいくつかのメソッドを実装する必要があります。通常、その仕事にはジェネリックを使用しますが、C にはジェネリックが用意されていないため、マクロを使用してそれらをエミュレートしようとしています。

これが私がやろうとしていることの例です:

#ifndef TYPE
#define TYPE int
#endif

TYPE get_minimum_##TYPE (TYPE * nums, int len){
    TYPE min = nums[0];

    for (int i = 1; i < len; i++) {
        if (nums[i] < min) {
            min = nums[i];
        }
    }

    return min;
}

ただし、これはコンパイルされません。クランエラーメッセージ:

エラー: 予想される ';' トップレベル宣言子の後

Cでこれを行う方法はありますか?または、すべてのタイプに対してこれを手動で実装する必要がありますか?

4

3 に答える 3

51

ヘッダーファイルで次のようなことができます:

//
// generic.h
//

#define TOKENPASTE(x, y) x ## y

#define GET_MINIMUM(T) TOKENPASTE(get_minimum_, T)

TYPE GET_MINIMUM (TYPE) (TYPE * nums, size_t len){
    TYPE min = nums[0];

    for (size_t i = 1; i < len; i++) {
        if (nums[i] < min) {
            min = nums[i];
        }
    }

    return min;
}

次に#include、必要なタイプごとにソースファイルに入れます。たとえば、次のようになります。

//
// generic.c
//

#define TYPE int
#include "generic.h"
#undef TYPE

#define TYPE float
#include "generic.h"
#undef TYPE

プリプロセッサを介して実行することで、これをテストできます。

$ gcc -E generic.c 

int get_minimum_int (int * nums, size_t len){
    int min = nums[0];

    for (size_t i = 1; i < len; i++) {
        if (nums[i] < min) {
            min = nums[i];
        }
    }

    return min;
}

float get_minimum_float (float * nums, size_t len){
    float min = nums[0];

    for (size_t i = 1; i < len; i++) {
        if (nums[i] < min) {
            min = nums[i];
        }
    }

    return min;
}
于 2013-05-13T12:46:38.650 に答える
41

実際にできる最善の方法は、指定された型の関数を生成するマクロを定義することです。

#define define_get_minimum(T) \
T get_minimum_##T(T* nums, int len){ \
    T min = nums[0]; \
    for (int i = 1; i < len; i++) { \
        if (nums[i] < min) { \
            min = nums[i]; \
        } \
    } \
    return min; \
}

次に、そのマクロを呼び出して、必要な特殊化を定義できます (C++ テンプレートを使用すると、同様のことがコンパイラによって自動的に行われます)。

define_get_minimum(int)
define_get_minimum(double)
define_get_minimum(float)

C++ コンパイラが自動的に行うもう 1 つのことは、必要なオーバーロードされた関数を推測することです。C ではそれを行うことはできないため、it 特殊化を使用していることを伝える必要があります。次のマクロを使用して、関数のテンプレートのような構文をシミュレートできます (C++<>は に置き換えられているだけです())。

#define get_minimum(T) get_minimum_##T

次に、次の方法で呼び出すことができるはずです。

int main()
{
    // Define arr as char* array...
    // Do stuff...
    int res = get_minimum(int)(arr, 3);
}

このコードはテストしていませんが、動作するはずです。

于 2013-05-13T13:56:18.237 に答える