C ++は非推奨としてマーク


147

インターフェイスに、移植可能なC ++で非推奨にするメソッドがあります。私がこれについてグーグル検索したとき、私が得たすべてはマイクロソフト固有のソリューションでした。#pragma deprecatedおよび__declspec(deprecated)

2番目の賞の解決策は、MSVCおよびGCCソリューションのifdefです。
ありがとう

回答:


193

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で非推奨としてマークする」を参照してください。


マクロで[[非推奨]]を使用できますか?
Daniel Ryan、

2
@Zammbiマクロはコンパイル前にプリプロセッサによって処理されるため、できるはずです。[[deprecated]]は、マクロが評価される場所に表示されます(そしてコンパイラに関連する警告が出力されます)。
フロリアンカステラーヌ

129

これでうまくいくはずです:

#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>、これはプリプロセッサーによってDEPRECATEDマクロに2つの引数を渡すと解釈されるためです。その場合は、戻り値の型をtypedefする必要があります。

編集:シンプルな(ただし、あまり互換性が低い可能性がある)バージョンはこちら


6
#errorの代わりに、#define DEPRECATED(func)func
CesarB

1
mxp:サポート終了は警告に過ぎないため、サポートされていないという警告で十分です。
Leon Timmermans、

1
うん、「#warningこのコンパイラにはDEPRECATEDを実装する必要があります」などと思います。それが不可能な場合、移植担当者はDEPRECATED(FUNC)FUNCを#defineし、それなしで生きることができます。
スティーブジェソップ

2
残念ながら、C ++:P #pragmaメッセージでコンパイル警告を出力する標準的な方法はありません。
Michael Platings 2008年

3
gccの属性構文では、属性を__declspec(deprecated)現在と同じ場所に配置できるため、マクロを簡略化できます。
bames53 2012年

57

ここに私の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);

以下も参照してください。


17
[[deprecate]]廃止されたマクロをどのように使用しますか?:-)
graham.reeds 2015年

3
これら2つの答えの間に大きな違いはありません。もう一度投稿したのはなぜですか。
トマーシュZato -復活モニカ

4
関数の周りにラップする必要はないので、DEPRECATED void foo(...);代わりにDEPRECATED(void foo(...));
dshepherd

12
新しい回答を投稿するのではなく、2008年の回答を編集する必要があります。
Yakov Galka

4
これは他の回答ほど広く互換性がない可能性があるため、個別に追加しました。
Michael Platings

22

GCCでは、次のように非推奨の属性を使用して関数を宣言できます。

void myfunc() __attribute__ ((deprecated));

これにより、その関数が.cファイルで使用されると、コンパイル時の警告がトリガーされます。

詳細については、http: //gcc.gnu.org/onlinedocs/gcc/Pragmas.htmlの「Diagnosticプラグマ」を参照して ください。


8

2018年のより完全な回答を次に示します。

最近では、多くのツールを使用して、何かを非推奨としてマークするだけでなく、メッセージを提供することもできます。これにより、何かが非推奨になったことを人々に知らせ、おそらく代替品に向けることができます。

コンパイラーのサポートにはまだ多くの種類があります。

  • C ++ 14は[[deprecated]]/をサポートしています[[deprecated(message)]]
  • __attribute__((deprecated)) GCC 4.0+およびARM 4.1+でサポートされています
  • __attribute__((deprecated))との__attribute__((deprecated(message)))ためにサポートされています:
    • GCC 4.5以降
    • GCC 4.5+になりすましたコンパイラー(__GNUC__/ __GNUC_MINOR__/を設定__GNUC_PATCHLEVEL__
    • Intel C / C ++コンパイラが少なくとも16に戻る(信頼できない__GNUC__/ __GNUC_MINOR__、インストールされているGCCのバージョンに設定するだけ)
    • ARM 5.6以降
  • MSVCは__declspec(deprecated)13.10以降をサポート(Visual Studio 2003)
  • MSVCは__declspec(deprecated(message))14.0以降をサポート(Visual Studio 2005)

[[gnu::deprecated]]に基づいて、C ++ 11の最近のバージョンのclang でも使用でき__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マクロとマクロを削除する方法を理解するための演習として残します(ヘドレーは主に書いたので、定期的に考える必要はありません)。

GLibを使用している場合は、G_DEPRECATEDおよびG_DEPRECATED_FORマクロを使用できます。これらはHedleyのものほど堅牢ではありませんが、すでにGLibを使用している場合は、追加するものはありません。


4

ポータブルプロジェクトを扱う場合、ある時点で、さまざまなプラットフォームの前処理済みの代替のセクションが必要になることはほぼ避けられません。#ifdef this #ifdef thatなど。

このようなセクションでは、シンボルを廃止する方法を条件付きで非常に適切に定義できます。ほとんどのツールチェーンはカスタムコンパイラ警告をサポートしているため、私の好みは通常「警告」マクロを定義することです。次に、非推奨などの特定の警告マクロを続行できます。専用の非推奨メソッドをサポートするプラットフォームでは、警告の代わりにそれを使用できます。


1

Intel Compiler v19.0の場合、これを__INTEL_COMPILER評価して1900次のように評価します。

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

次の言語レベルで機能します。

  • C ++ 17サポート(/ Qstd = c ++ 17)
  • C ++ 14サポート(/ Qstd = c ++ 14)
  • C ++ 11サポート(/ Qstd = c ++ 11)
  • C11サポート(/ Qstd = c11)
  • C99サポート(/ Qstd = c99)

インテルコンパイラーには[[deprecated]]、他のすべてのコンパイラーが行う特定の言語要素の属性をサポートしないというバグがあるようです。例として、GitHubの(非常に優れた){fmtlib / fmt}ライブラリのv6.0.0をインテルコンパイラーv19.0でコンパイルします。壊れます。次に、GitHubコミットの修正を参照してください。


これは誤りです。C ++属性は、ICCのCモードでは機能しません。 __attribute__((deprecated))、OTOHはCとC ++で動作し、少なくともICC 13.0まで遡ります。おそらくそれ以上(Intelはこのタイプのものを文書化しない傾向があるため、確信が持てません)。
nemequ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.