Tanda C ++ sudah usang


147

Saya memiliki metode dalam antarmuka yang ingin saya hilangkan dengan portable C ++. Ketika saya mencari Google untuk ini semua yang saya dapatkan adalah solusi spesifik Microsoft; #pragma sudah usang dan __declspec (sudah usang) .

Solusi hadiah kedua adalah untuk ifdef solusi MSVC dan GCC.
Terima kasih

Jawaban:


193

Dalam C ++ 14, Anda dapat menandai fungsi yang sudah usang menggunakan [[deprecated]]atribut (lihat bagian 7.6.5 [dcl.attr.deprecated]).

The atribut-tanda deprecated dapat digunakan untuk nama-nama merek dan entitas yang penggunaannya masih diperbolehkan, namun tidak dianjurkan untuk beberapa alasan.

Misalnya, fungsi berikut footidak digunakan lagi:

[[deprecated]]
void foo(int);

Dimungkinkan untuk memberikan pesan yang menjelaskan mengapa nama atau entitas tidak digunakan lagi:

[[deprecated("Replaced by bar, which has an improved interface")]]
void foo(int);

Pesan harus berupa string literal.

Untuk detail lebih lanjut, lihat “Menandai sebagai usang dalam C ++ 14” .


Bisakah Anda menggunakan [[usang]] di makro?
Daniel Ryan

2
@Zammbi Anda seharusnya bisa, karena makro ditangani oleh preprocessor sebelum kompilasi. [[usang]] akan muncul (dan biarkan peringatan yang terkait keluaran kompilator) tempat makro dievaluasi.
Florian Castellane

129

Ini harus melakukan trik:

#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);

Namun, Anda akan mengalami masalah jika tipe fungsi kembali memiliki koma dalam namanya misalnya std::pair<int, int>karena ini akan ditafsirkan oleh preprocesor sebagai melewati 2 argumen ke makro DEPRECATED. Dalam hal ini Anda harus mengetikkan tipe kembali.

Sunting: versi yang lebih sederhana (tetapi mungkin kurang kompatibel) di sini .


6
Alih-alih #error, akan lebih baik untuk #define DEPRECATED (func) func
CesarB

1
mxp: Penghentian hanya peringatan, dan karenanya saya akan mengatakan bahwa peringatan yang tidak didukung adalah semua yang Anda butuhkan.
Leon Timmermans

1
Yap, saya akan pergi untuk "#warning Anda perlu mengimplementasikan DIPRESEKSI untuk kompiler ini", atau semacamnya. Jika itu tidak mungkin, maka porter dapat #mendefinisikan DEPRECATED (FUNC) FUNC, dan hidup tanpanya.
Steve Jessop

2
Sayangnya tidak ada cara standar untuk menampilkan peringatan kompilasi di C ++: P #pragma harus dilakukan.
Michael Platings

3
Sintaks atribut gcc memungkinkan atribut berada di tempat yang sama seperti __declspec(deprecated)sekarang, sehingga makro dapat disederhanakan.
bames53

57

Inilah versi sederhana jawaban saya 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);

Lihat juga:


17
Bagaimana Anda [[deprecate]]macro Anda yang sudah usang? :-)
graham.reeds

3
Saya tidak dapat melihat perbedaan yang signifikan antara kedua jawaban itu. Mengapa Anda mempostingnya untuk kedua kalinya?
Tomáš Zato - Reinstate Monica

4
Anda tidak harus membungkusnya di sekitar fungsi sehingga DEPRECATED void foo(...);bukanDEPRECATED(void foo(...));
dshepherd

12
Anda seharusnya mengedit jawaban 2008 Anda daripada memposting yang baru.
Yakov Galka

4
Ini mungkin tidak kompatibel secara luas dengan jawaban saya yang lain, maka saya menambahkan ini secara terpisah.
Michael Platings

22

Di GCC, Anda dapat mendeklarasikan fungsi Anda dengan atribut yang tidak digunakan lagi seperti ini:

void myfunc() __attribute__ ((deprecated));

Ini akan memicu peringatan waktu kompilasi ketika fungsi itu digunakan dalam file .c.

Anda dapat menemukan lebih banyak info di bawah "Pragma diagnostik" di http://gcc.gnu.org/onlinedocs/gcc/Pragmas.html


8

Ini jawaban yang lebih lengkap untuk 2018.

Saat ini, banyak alat memungkinkan Anda untuk tidak hanya menandai sesuatu yang sudah usang, tetapi juga memberikan pesan. Ini memungkinkan Anda memberi tahu orang-orang ketika ada sesuatu yang sudah ketinggalan zaman, dan mungkin mengarahkan mereka ke pengganti.

Masih ada banyak variasi dalam dukungan compiler:

  • C ++ 14 mendukung [[deprecated]]/ [[deprecated(message)]].
  • __attribute__((deprecated)) didukung oleh GCC 4.0+ dan ARM 4.1+
  • __attribute__((deprecated))dan __attribute__((deprecated(message)))didukung untuk:
    • GCC 4.5+
    • Beberapa kompiler yang menyamar sebagai GCC 4.5+ (dengan menetapkan __GNUC__/ __GNUC_MINOR__/ __GNUC_PATCHLEVEL__)
    • Intel C / C ++ Compiler akan kembali ke setidaknya 16 (Anda tidak bisa percaya __GNUC__/ __GNUC_MINOR__, mereka hanya mengaturnya ke versi GCC apa pun yang diinstal)
    • ARM 5.6+
  • MSVC mendukung __declspec(deprecated)sejak 13.10 (Visual Studio 2003)
  • MSVC mendukung __declspec(deprecated(message))sejak 14.0 (Visual Studio 2005)

Anda juga dapat menggunakan [[gnu::deprecated]]dentang versi terbaru di C ++ 11, berdasarkan __has_cpp_attribute(gnu::deprecated).

Saya memiliki beberapa makro di Hedley untuk menangani semua ini secara otomatis yang saya perbarui, tetapi versi saat ini (v2) terlihat seperti ini:

#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

Saya akan meninggalkannya sebagai latihan untuk mengetahui cara menyingkirkan *_VERSION_CHECKdan *_HAS_ATTRIBUTEmakro jika Anda tidak ingin menggunakan Hedley (saya menulis Hedley sebagian besar jadi saya tidak perlu memikirkannya secara teratur).

Jika Anda menggunakan GLib, Anda bisa menggunakan G_DEPRECATEDdan G_DEPRECATED_FORmakro. Mereka tidak sekuat yang dari Hedley, tetapi jika Anda sudah menggunakan GLib tidak ada yang perlu ditambahkan.


4

Berurusan dengan proyek portabel hampir tidak dapat dihindari bahwa Anda pada suatu saat membutuhkan bagian dari alternatif yang telah diproses untuk berbagai platform. #Jika ini #Jika itu dan sebagainya.

Di bagian seperti itu Anda bisa menentukan cara penghentian simbol dengan sangat baik. Preferensi saya biasanya untuk mendefinisikan makro "peringatan" karena sebagian besar alat bantu mendukung peringatan kompiler khusus. Kemudian Anda bisa melanjutkan dengan makro peringatan spesifik untuk penghentian dll. Untuk platform yang mendukung metode penghentian khusus Anda dapat menggunakannya sebagai ganti peringatan.


1

Untuk Intel Compiler v19.0, gunakan ini sebagai __INTEL_COMPILERevaluasi untuk 1900:

#  if defined(__INTEL_COMPILER)
#    define DEPRECATED [[deprecated]]
#  endif

Berfungsi untuk level bahasa berikut:

  • Dukungan C ++ 17 (/ Qstd = c ++ 17)
  • Dukungan C ++ 14 (/ Qstd = c ++ 14)
  • Dukungan C ++ 11 (/ Qstd = c ++ 11)
  • Dukungan C11 (/ Qstd = c11)
  • Dukungan C99 (/ Qstd = c99)

Intel Compiler memiliki bug yang muncul karena tidak mendukung [[deprecated]]atribut pada elemen bahasa tertentu yang dilakukan oleh semua kompiler lain. Sebagai contoh, kompilasi pustaka {fmtlib / fmt} v6.0.0 (sangat luar biasa) di GitHub dengan Intel Compiler v19.0. Itu akan pecah. Kemudian lihat perbaikan di komit GitHub .


Ini salah; Atribut C ++ tidak berfungsi dalam mode C pada ICC. Contoh . __attribute__((deprecated)), OTOH, bekerja di C dan C ++ akan kembali ke setidaknya ICC 13.0, mungkin jauh lebih lanjut (Intel cenderung tidak mendokumentasikan hal-hal semacam ini jadi saya tidak bisa memastikan).
nemequ
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.