ฉันมีวิธีการในอินเทอร์เฟซที่ฉันต้องการคัดค้านด้วยพกพา C ++ เมื่อฉัน Googled สำหรับสิ่งนี้ทั้งหมดที่ฉันได้รับคือโซลูชันเฉพาะของ Microsoft; #pragma เลิกและ__declspec (เลิกใช้)
ทางออกที่สองที่ได้รับรางวัลคือการแก้ปัญหา MSVC และ GCC
ขอบคุณ
ฉันมีวิธีการในอินเทอร์เฟซที่ฉันต้องการคัดค้านด้วยพกพา C ++ เมื่อฉัน Googled สำหรับสิ่งนี้ทั้งหมดที่ฉันได้รับคือโซลูชันเฉพาะของ Microsoft; #pragma เลิกและ__declspec (เลิกใช้)
ทางออกที่สองที่ได้รับรางวัลคือการแก้ปัญหา MSVC และ GCC
ขอบคุณ
คำตอบ:
ใน C ++ 14 คุณสามารถทำเครื่องหมายฟังก์ชันว่าเลิกใช้แล้วโดยใช้[[deprecated]]
แอตทริบิวต์ (ดูหัวข้อ 7.6.5 [dcl.attr.deprecated])
แอตทริบิวต์โทเค็น
deprecated
สามารถนำไปใช้ชื่อเครื่องหมายและหน่วยงานที่มีการใช้งานจะยังคงได้รับอนุญาต แต่เป็นกำลังใจด้วยเหตุผลบางอย่าง
ตัวอย่างเช่นฟังก์ชันต่อไปfoo
นี้เลิกใช้แล้ว:
[[deprecated]]
void foo(int);
เป็นไปได้ที่จะให้ข้อความที่อธิบายถึงสาเหตุที่ชื่อหรือเอนทิตีถูกเลิกใช้:
[[deprecated("Replaced by bar, which has an improved interface")]]
void foo(int);
ข้อความต้องเป็นตัวอักษรสตริง
สำหรับรายละเอียดเพิ่มเติมโปรดดูที่“การทำเครื่องหมายว่าเลิกใช้ใน C ++ 14”
สิ่งนี้ควรทำเคล็ดลับ:
#ifdef __GNUC__
#define DEPRECATED(func) func __attribute__ ((deprecated))
#elif defined(_MSC_VER)
#define DEPRECATED(func) __declspec(deprecated) func
#else
#pragma message("WARNING: You need to implement DEPRECATED for this compiler")
#define DEPRECATED(func) func
#endif
...
//don't use me any more
DEPRECATED(void OldFunc(int a, float b));
//use me instead
void NewFunc(int a, double b);
อย่างไรก็ตามคุณจะพบปัญหาหากประเภทการคืนค่าฟังก์ชันมีเครื่องหมายจุลภาคในชื่อของมันเช่นstd::pair<int, int>
นี้จะถูกตีความโดย preprocesor เป็นผ่าน 2 ข้อโต้แย้งไปยังแมโครเลิกใช้ ในกรณีนั้นคุณจะต้องพิมพ์ประเภทผลตอบแทน
แก้ไข: ง่าย ( แต่อาจเป็นไปได้น้อยที่เข้ากันได้อย่างกว้างขวาง) รุ่นที่นี่
__declspec(deprecated)
ตอนนี้ดังนั้นแมโคจึงสามารถทำให้ง่ายขึ้นได้
ต่อไปนี้เป็นคำตอบที่เรียบง่ายของปี 2008ของฉัน:
#if defined(__GNUC__) || defined(__clang__)
#define DEPRECATED __attribute__((deprecated))
#elif defined(_MSC_VER)
#define DEPRECATED __declspec(deprecated)
#else
#pragma message("WARNING: You need to implement DEPRECATED for this compiler")
#define DEPRECATED
#endif
//...
//don't use me any more
DEPRECATED void OldFunc(int a, float b);
//use me instead
void NewFunc(int a, double b);
ดูสิ่งนี้ด้วย:
[[deprecate]]
แมโครเลิกใช้ของคุณหรือไม่ :-)
DEPRECATED void foo(...);
แทนที่จะเป็นDEPRECATED(void foo(...));
ใน GCC คุณสามารถประกาศฟังก์ชั่นของคุณด้วยแอตทริบิวต์ที่เลิกใช้เช่นนี้:
void myfunc() __attribute__ ((deprecated));
สิ่งนี้จะทริกเกอร์การเตือนเวลาคอมไพล์เมื่อฟังก์ชันนั้นถูกใช้ในไฟล์. c
คุณสามารถค้นหาข้อมูลเพิ่มเติมภายใต้ "การวินิจฉัย pragmas" ได้ที่ http://gcc.gnu.org/onlinedocs/gcc/Pragmas.html
นี่คือคำตอบที่สมบูรณ์ยิ่งขึ้นสำหรับปี 2561
วันนี้มีเครื่องมือมากมายที่ช่วยให้คุณไม่เพียง แต่ทำเครื่องหมายว่าเลิกใช้แล้ว แต่ยังมีข้อความ วิธีนี้ช่วยให้คุณสามารถบอกผู้คนเมื่อมีบางสิ่งไม่เป็นที่ยอมรับ
ยังมีความหลากหลายในการรองรับคอมไพเลอร์:
[[deprecated]]
[[deprecated(message)]]
__attribute__((deprecated))
ได้รับการสนับสนุนโดย GCC 4.0+ และ ARM 4.1+__attribute__((deprecated))
และ__attribute__((deprecated(message)))
ได้รับการสนับสนุนสำหรับ:
__GNUC__
/ __GNUC_MINOR__
/ __GNUC_PATCHLEVEL__
)__GNUC__
/ __GNUC_MINOR__
พวกเขาเพิ่งตั้งค่าเป็น GCC รุ่นใดก็ตามที่ติดตั้ง)__declspec(deprecated)
ตั้งแต่ 13.10 (Visual Studio 2003)__declspec(deprecated(message))
ตั้งแต่ 14.0 (Visual Studio 2005)นอกจากนี้คุณยังสามารถใช้[[gnu::deprecated]]
ในรุ่นที่ผ่านมาของเสียงดังกราวใน C ++ 11 __has_cpp_attribute(gnu::deprecated)
ขึ้นอยู่กับ
ฉันมีมาโครบางตัวในHedleyเพื่อจัดการทั้งหมดนี้โดยอัตโนมัติซึ่งเป็นรุ่นล่าสุด แต่รุ่นปัจจุบัน (v2) มีลักษณะดังนี้:
#if defined(__cplusplus) && (__cplusplus >= 201402L)
# define HEDLEY_DEPRECATED(since) [[deprecated("Since " #since)]]
# define HEDLEY_DEPRECATED_FOR(since, replacement) [[deprecated("Since " #since "; use " #replacement)]]
#elif \
HEDLEY_GCC_HAS_EXTENSION(attribute_deprecated_with_message,4,5,0) || \
HEDLEY_INTEL_VERSION_CHECK(16,0,0) || \
HEDLEY_ARM_VERSION_CHECK(5,6,0)
# define HEDLEY_DEPRECATED(since) __attribute__((__deprecated__("Since " #since)))
# define HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__("Since " #since "; use " #replacement)))
#elif \
HEDLEY_GCC_HAS_ATTRIBUTE(deprcated,4,0,0) || \
HEDLEY_ARM_VERSION_CHECK(4,1,0)
# define HEDLEY_DEPRECATED(since) __attribute__((__deprecated__))
# define HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__))
#elif HEDLEY_MSVC_VERSION_CHECK(14,0,0)
# define HEDLEY_DEPRECATED(since) __declspec(deprecated("Since " # since))
# define HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated("Since " #since "; use " #replacement))
#elif HEDLEY_MSVC_VERSION_CHECK(13,10,0)
# define HEDLEY_DEPRECATED(since) _declspec(deprecated)
# define HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated)
#else
# define HEDLEY_DEPRECATED(since)
# define HEDLEY_DEPRECATED_FOR(since, replacement)
#endif
ฉันจะปล่อยให้มันเป็นแบบฝึกหัดเพื่อหาวิธีกำจัด*_VERSION_CHECK
และ*_HAS_ATTRIBUTE
มาโครหากคุณไม่ต้องการใช้ Hedley (ฉันเขียน Hedley เป็นส่วนใหญ่ดังนั้นฉันไม่ต้องคิดเรื่องนี้เป็นประจำ)
หากคุณใช้ GLib คุณสามารถใช้G_DEPRECATED
และG_DEPRECATED_FOR
มาโครได้ มันไม่แข็งแกร่งเท่า Hedley แต่ถ้าคุณใช้ GLib อยู่แล้วจะไม่มีอะไรเพิ่ม
การจัดการกับโปรเจ็กต์พกพาเป็นเรื่องที่หลีกเลี่ยงไม่ได้ที่คุณจะต้องมีส่วนของทางเลือกที่ประมวลผลล่วงหน้าแล้วสำหรับแพลตฟอร์มที่หลากหลาย #ifdef #ifdef นี้และอื่น ๆ
ในส่วนดังกล่าวคุณสามารถกำหนดวิธีในการตัดสัญลักษณ์ การตั้งค่าของฉันมักจะกำหนดมาโคร "คำเตือน" เนื่องจาก toolchains ส่วนใหญ่สนับสนุนคำเตือนคอมไพเลอร์ที่กำหนดเอง จากนั้นคุณสามารถใช้แมโครคำเตือนเฉพาะสำหรับการคัดค้านเป็นต้นสำหรับแพลตฟอร์มที่รองรับวิธีการคัดแยกเฉพาะคุณสามารถใช้วิธีนั้นแทนคำเตือน
สำหรับ Intel Compiler v19.0 ให้ใช้สิ่งนี้ตามการ__INTEL_COMPILER
ประเมินเพื่อ1900
:
# if defined(__INTEL_COMPILER)
# define DEPRECATED [[deprecated]]
# endif
ใช้งานได้กับระดับภาษาต่อไปนี้:
Intel Compiler มีข้อผิดพลาดที่ปรากฏซึ่งไม่สนับสนุน[[deprecated]]
คุณลักษณะในองค์ประกอบภาษาบางอย่างที่คอมไพเลอร์อื่น ๆ ทำ ตัวอย่างเช่นคอมไพล์ v6.0.0 ของไลบรารี (ยอดเยี่ยมอย่างน่าทึ่ง) {fmtlib / fmt}บน GitHub พร้อม Intel Compiler v19.0 มันจะพัง แล้วเห็นผลการแก้ไขใน GitHub กระทำ
__attribute__((deprecated))
, OTOH, ทำงานใน C และ C ++ กลับไปที่ ICC 13.0 เป็นอย่างน้อย, อาจจะมากขึ้นไปอีก (Intel มักจะไม่บันทึกเอกสารประเภทนี้ดังนั้นฉันจึงไม่แน่ใจ)