จะใช้มาโครใน C เพื่อเลือกประเภทและฟังก์ชั่นเฉพาะตามประเภทที่เลือกได้อย่างไร

ฉันมีโค้ด C ส่วนหนึ่งซึ่งฉันกำหนดโครงสร้างข้อมูลบางส่วนเป็นประเภทพื้นฐาน ฉันต้องการกำหนดประเภทพื้นฐานนี้ผ่านมาโครเพื่อให้สามารถเปลี่ยนแปลงได้ บางอย่าง la:

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

ด้วยเหตุนี้ ฉันจึงต้องเลือกฟังก์ชันที่เหมาะสมเล็กน้อยโดยขึ้นอยู่กับประเภท ตัวอย่างเช่น สำหรับ float ฉันควรใช้ fabsf จาก <cmath> แต่สำหรับ double ฉันควรใช้ fabs บางสิ่งบางอย่าง la:

#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

แต่ดูเหมือนว่าจะไม่ทำงาน: คอมไพเลอร์ของฉันให้คำเตือนประเภทนี้:

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)
                ^~~~~

มีความคิดใดที่ฉันจะสร้างงานแบบนี้ได้อย่างไร? ฉันน่าจะพลาดบางอย่างเกี่ยวกับวิธีใช้มาโคร


person Zorglub29    schedule 24.04.2021    source แหล่งที่มา
comment
คุณสามารถแก้ไขปัญหานี้ได้ด้วยมาโคร แต่มีเหตุผลว่าทำไม _Generic ไม่ทำ ไม่ทำงานเหรอ?   -  person H Walters    schedule 24.04.2021
comment
อ่า คุณพูดถูก นี่อาจเป็นวิธีแก้ปัญหา ฉันแค่ไม่คุ้นเคยกับมัน   -  person Zorglub29    schedule 24.04.2021


คำตอบ (1)


ตามที่แนะนำในความคิดเห็น _Generic จะทำเคล็ดลับ อย่างไรก็ตาม ด้วยเหตุผลอื่นบางประการ ฉันยังคงต้องการยึดติดกับแฟล็กและมาโครและตรรกะ #define รายการ สำหรับบันทึกต่างๆ นี่คือวิธีแก้ปัญหาที่ฉันใช้ อาจจะละเอียดไปหน่อย (แจ้งให้เราทราบหากคุณรู้บางสิ่งที่ดีกว่า :)) แต่ใช้กลอุบาย:

#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