Dấu C ++ không dùng nữa


147

Tôi có một phương thức trong một giao diện mà tôi muốn phản đối với C ++ di động. Khi tôi làm việc này, tất cả những gì tôi nhận được là một giải pháp cụ thể của Microsoft; #pragma không dùng nữa__declspec (không dùng nữa) .

Một giải pháp giải thưởng thứ hai sẽ là ifdef một MSVC và một giải pháp GCC.
Cảm ơn

Câu trả lời:


193

Trong C ++ 14, bạn có thể đánh dấu một hàm là không dùng nữa bằng cách sử dụng [[deprecated]]thuộc tính (xem phần 7.6.5 [dcl.attr.deprecated]).

thông báo thuộc tính deprecated có thể được sử dụng để đánh dấu tên và thực thể mà việc sử dụng vẫn được cho phép, nhưng không được khuyến khích vì một số lý do.

Ví dụ: hàm sau fookhông được dùng nữa:

[[deprecated]]
void foo(int);

Có thể cung cấp một thông báo mô tả lý do tại sao tên hoặc thực thể bị phản đối:

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

Thông điệp phải là một chuỗi bằng chữ.

Để biết thêm chi tiết, hãy xem Mark Marking là không dùng nữa trong C ++ 14 .


Bạn có thể sử dụng [[deprecated]] trong macro không?
Daniel Ryan

2
@Zammbi Bạn sẽ có thể, vì macro được xử lý bởi bộ tiền xử lý trước khi biên dịch. [[deprecated]] sẽ xuất hiện (và để các cảnh báo liên quan đến đầu ra của trình biên dịch) trong đó macro được ước tính.
Florian Castellane

129

Cái này cần phải dùng mẹo:

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

Tuy nhiên, bạn sẽ gặp phải vấn đề nếu một kiểu trả về hàm có dấu phẩy trong tên của nó, ví dụ std::pair<int, int>như điều này sẽ được người tiền xử lý hiểu là chuyển 2 đối số cho macro ĐỔI. Trong trường hợp đó, bạn sẽ phải gõ kiểu trả về.

Chỉnh sửa: phiên bản đơn giản hơn (nhưng có thể ít tương thích rộng rãi hơn) tại đây .


6
Thay vì #error, sẽ tốt hơn nếu #define DEPRECATED (func) func
CesarB

1
mxp: Sự phản đối chỉ là một cảnh báo và do đó tôi muốn nói rằng một cảnh báo rằng nó không được hỗ trợ là tất cả những gì bạn cần.
Leon Timmermans

1
Đúng, tôi sẽ sử dụng "#warning Bạn cần triển khai TIẾP TỤC cho trình biên dịch này" hoặc một số thứ tương tự. Nếu điều đó là không thể, thì porter có thể #define DEPRECATED (FUNC) FUNC và sống mà không cần nó.
Steve Jessop

2
Thật không may, không có cách tiêu chuẩn nào để đưa ra cảnh báo biên dịch trong C ++: P #pragma sẽ phải thực hiện.
Michael Platings

3
Cú pháp thuộc tính của gcc cho phép thuộc tính ở cùng một vị trí như __declspec(deprecated)bây giờ, vì vậy macro có thể được đơn giản hóa.
bames53

57

Đây là phiên bản đơn giản hóa của câu trả lời năm 2008 của tôi :

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

Xem thêm:


17
Làm thế nào để bạn [[deprecate]]macro không dùng nữa? :-)
graham.reeds

3
Tôi không thể thấy bất kỳ sự khác biệt đáng kể giữa hai câu trả lời. Tại sao bạn đăng nó lần thứ hai?
Tomáš Zato - Phục hồi Monica

4
Bạn không cần phải bọc nó xung quanh chức năng vì vậy nó DEPRECATED void foo(...);thay vìDEPRECATED(void foo(...));
dshepherd

12
Bạn nên chỉnh sửa câu trả lời năm 2008 của bạn thay vì đăng một câu trả lời mới.
Yakov Galka

4
Điều này có thể không tương thích rộng rãi như câu trả lời khác của tôi, do đó tôi đã thêm nó một cách riêng biệt.
Michael Platings

22

Trong GCC, bạn có thể khai báo hàm của mình với thuộc tính không dùng nữa như sau:

void myfunc() __attribute__ ((deprecated));

Điều này sẽ kích hoạt cảnh báo thời gian biên dịch khi hàm đó được sử dụng trong tệp .c.

Bạn có thể tìm thêm thông tin trong phần "Chẩn đoán pragmas" tại http://gcc.gnu.org/onlinesocs/gcc/Pragmas.html


8

Dưới đây là một câu trả lời đầy đủ hơn cho năm 2018.

Ngày nay, rất nhiều công cụ cho phép bạn không chỉ đánh dấu một cái gì đó bị phản đối mà còn cung cấp một thông điệp. Điều này cho phép bạn nói với mọi người khi một cái gì đó không được chấp nhận và có thể hướng họ đến một sự thay thế.

Vẫn còn rất nhiều sự hỗ trợ trong trình biên dịch:

  • C ++ 14 hỗ trợ [[deprecated]]/ [[deprecated(message)]].
  • __attribute__((deprecated)) được hỗ trợ bởi GCC 4.0+ và ARM 4.1+
  • __attribute__((deprecated))__attribute__((deprecated(message)))được hỗ trợ cho:
    • GCC 4.5+
    • Một số trình biên dịch giả dạng GCC 4.5+ (bằng cách đặt __GNUC__/ __GNUC_MINOR__/__GNUC_PATCHLEVEL__ )
    • Trình biên dịch Intel C / C ++ trở lại ít nhất 16 (bạn không thể tin tưởng __GNUC__/ __GNUC_MINOR__, họ chỉ cần đặt nó thành bất kỳ phiên bản GCC nào được cài đặt)
    • ARM 5.6+
  • MSVC hỗ trợ __declspec(deprecated)kể từ ngày 13.10 (Visual Studio 2003)
  • MSVC hỗ trợ __declspec(deprecated(message))kể từ 14.0 (Visual Studio 2005)

Bạn cũng có thể sử dụng [[gnu::deprecated]]các phiên bản clang gần đây trong C ++ 11, dựa trên __has_cpp_attribute(gnu::deprecated).

Tôi có một số macro trong Hedley để tự động xử lý tất cả những điều này mà tôi luôn cập nhật, nhưng phiên bản hiện tại (v2) trông như thế này:

#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

Tôi sẽ để nó như một bài tập để tìm ra cách thoát khỏi *_VERSION_CHECK*_HAS_ATTRIBUTE macro nếu bạn không muốn sử dụng Hedley (Tôi đã viết phần lớn Hedley vì vậy tôi sẽ không phải suy nghĩ về điều đó một cách thường xuyên).

Nếu bạn sử dụng GLib, bạn có thể sử dụng G_DEPRECATEDG_DEPRECATED_FORmacro. Chúng không mạnh như của Hedley, nhưng nếu bạn đã sử dụng GLib thì không có gì để thêm.


4

Đối phó với các dự án di động, gần như không thể tránh khỏi việc bạn cần một phần thay thế được xử lý trước cho một loạt các nền tảng. #ifdef này #ifdef đó và vân vân.

Trong một phần như vậy, bạn rất có thể xác định một cách có điều kiện một cách để loại bỏ các biểu tượng. Sở thích của tôi thường là xác định macro "cảnh báo" vì hầu hết các công cụ hỗ trợ cảnh báo trình biên dịch tùy chỉnh. Sau đó, bạn có thể tiếp tục với một macro cảnh báo cụ thể cho việc khấu hao, vv Đối với các nền tảng hỗ trợ các phương pháp khấu hao chuyên dụng, bạn có thể sử dụng thay vì cảnh báo.


1

Đối với Intel Compiler v19.0, hãy sử dụng điều này để __INTEL_COMPILERđánh giá 1900:

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

Hoạt động cho các cấp độ ngôn ngữ sau:

  • Hỗ trợ C ++ 17 (/ Qstd = c ++ 17)
  • Hỗ trợ C ++ 14 (/ Qstd = c ++ 14)
  • Hỗ trợ C ++ 11 (/ Qstd = c ++ 11)
  • Hỗ trợ C11 (/ Qstd = c11)
  • Hỗ trợ C99 (/ Qstd = c99)

Trình biên dịch Intel có lỗi xuất hiện ở chỗ nó không hỗ trợ [[deprecated]]thuộc tính trên các thành phần ngôn ngữ nhất định mà tất cả các trình biên dịch khác làm. Ví dụ, biên dịch v6.0.0 của thư viện {fmtlib / fmt} (cực kỳ xuất sắc) trên GitHub với Intel Compiler v19.0. Nó sẽ vỡ. Sau đó xem bản sửa lỗi trong cam kết GitHub .


Điều này là không đúng; Các thuộc tính C ++ không hoạt động trong chế độ C trên ICC. Thí dụ . __attribute__((deprecated)), OTOH, hoạt động trong C và C ++ trở lại ít nhất là ICC 13.0, có thể xa hơn nữa (Intel có xu hướng không ghi lại loại công cụ này vì vậy tôi không chắc chắn).
nemequ
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.