Bagaimana cara menggunakan makro di C untuk memilih tipe dan fungsi tertentu tergantung pada tipe yang dipilih?

Saya memiliki sepotong kode C tempat saya mendefinisikan beberapa struktur data pada tipe dasar. Saya ingin mendefinisikan tipe fundamental ini melalui makro agar dapat diubah, sesuatu yang ala:

#define F_TYPE float                  // will use float as the fundamental type
// #define F_TYPE double                 // will use double instead

Sebagai konsekuensinya, saya perlu melakukan sedikit pemilihan fungsi yang tepat tergantung pada jenisnya. Misalnya, untuk float saya harus menggunakan fabsf dari <cmath>, tetapi untuk double saya harus menggunakan fabs. Sesuatu yang ala:

#if (F_TYPE == float)
    #define F_TYPE_ABS(x) fabsf(x)
#elif (F_TYPE == double)
    #define F_TYPE_ABS(x) fabs(x)
#else
    #error "need to specify math functions to use with type F_TYPE"
#endif

Tapi ini sepertinya tidak berhasil: kompiler saya memberikan peringatan seperti itu:

In file included from tests_vec3.cpp:2:0:
../src/kiss_clang_3d.h:27:16: warning: "double" is not defined, evaluates to 0 [-Wundef]
 #define F_TYPE double
                ^
../src/kiss_clang_3d.h:32:6: note: in expansion of macro ‘F_TYPE’
 #if (F_TYPE == float)
      ^~~~~~
../src/kiss_clang_3d.h:32:16: warning: "float" is not defined, evaluates to 0 [-Wundef]
 #if (F_TYPE == float)
                ^~~~~

Adakah yang tahu bagaimana saya bisa membuat sesuatu seperti ini berhasil? Kemungkinan besar saya melewatkan sesuatu tentang bagaimana saya harus menggunakan makro.


person Zorglub29    schedule 24.04.2021    source sumber
comment
Anda dapat mengatasi masalah ini dengan makro, tetapi apakah ada alasan mengapa _Generic tidak tidak berfungsi?   -  person H Walters    schedule 24.04.2021
comment
Aaah, kamu benar, ini mungkin solusinya. Saya hanya tidak mengenalnya.   -  person Zorglub29    schedule 24.04.2021


Jawaban (1)


Seperti yang disarankan dalam komentar, _Generic akan berhasil. Namun, untuk beberapa alasan lain, saya masih ingin tetap menggunakan beberapa flag dan #define makro dan logika. Sebagai catatan, solusi inilah yang akhirnya saya gunakan; mungkin agak bertele-tele (beri tahu saya jika Anda mengetahui sesuatu yang lebih baik :)), tetapi berhasil:

#define XSTR(x) STR(x)
#define STR(x) #x

// what fundamental type do we want to use?
// if the F_TYPE_SWITCH is set (by defining the macro earlier, either before #includ-ing, or
// by defining the compilation flag -DF_TYPE_SWITCH="'X'" where X is the type flag wanted),
// use it, otherwise, use the value set under.
#ifndef F_TYPE_SWITCH
  // double is 'D', float is 'F'
  #define F_TYPE_SWITCH 'D'
#endif

// this is C, no overloading, we need to adapt a bit to what sort of fundamental type we want to use
#if (F_TYPE_SWITCH == 'F')
    #define F_TYPE_2 (2.0f)

    #define F_TYPE_ABS(x) fabsf(x)

#elif (F_TYPE_SWITCH == 'D')
    #define F_TYPE_2 (2.0)

    #define F_TYPE_ABS(x) fabs(x)
#else
    #pragma message "The value of F_TYPE_SWITCH: " XSTR(F_TYPE_SWITCH)
    #error "invalid F_TYPE_SWITCH admissible switches are F (float) and D (double)"
#endif
person Zorglub29    schedule 25.04.2021