windows.hが含まれているとstd :: minが失敗するのはなぜですか?


106
#include <algorithm>
#include <Windows.h>

int main()
{
    int k = std::min(3, 4);
    return 0;
}

Windows.hをインクルードした場合、ウィンドウは何をしますか?std::minVisual Studio 2005 では使用できません。エラーメッセージは次のとおりです。

error C2589: '(' : illegal token on right side of '::'
error C2059: syntax error : '::'

回答:


155

windows.hヘッダファイル(またはより正確に、windef.hそれは順番に含まれていること)をするためのマクロを有し、minそしてmaxこれを妨害しています。

あなたは#define NOMINMAXそれを含める前にすべきです。


27
MACROSが悪である理由の1つ。:D
Nawaz

7
プロジェクト全体の/ D "NOMINMAX"を使用しました
Micka

@Micka:このオプションをプロジェクト設定のどこに配置しましたか?同じオプションを使用する必要があり、どこに配置すればよいかわからない...
flaviu2

@ flaviu2は、すべてのコンパイルコマンドが要約されているページの「追加コマンド」フィールドに表示されます。しかし、現時点では確認できません
Micka

それは追加することでした:#include <algorithm> + NOMINMAX
user63898

89

何も定義する必要はなく、次の構文を使用してマクロをバイパスするだけです。

(std::min)(a, b); // added parentheses around function name
(std::max)(a, b);

1
ありがとう、これは私のために働いたソリューションです。コードの一部がマクロを必要とするWindowsからの描画コードを使用するため、NOMINMAXを単純に使用できないコードに取り組んでいます。
ミカエル・C.ギマランイス

なぜ魔法の周りの括弧が邪悪なマクロを打ち負かすことができるのか説明してください!?クール
陳OT

1
ボンネットの下のすべての魔法について完全に確信はありませんが、マクロパーサーが正確に「min(」を置き換えることを検討しているため、「min)(」はマクロパーサーによって無視されます。意味のない()は、マクロ以外の問題を引き起こしません
PolyMesh

1
ニートソリューションが、名前と機能を持つことの問題のために解決していないminmax(サンプル使用事例:にそのフィットクラスを実装するUniformRandomNumberGeneratorの概念)。
Nik Bougalis

エリックの答えを見てください、私はそれがより良い解決策だと思います。ハックが少なく、クリアです。
PolyMesh

28

他の人が述べたように、エラーはウィンドウのヘッダーで定義されている最小/最大マクロが原因です。それらを無効にする方法は3つあります。

1)#define NOMINMAXヘッダーをインクルードする前に、これは一般に、次のヘッダーに影響を与えるためにマクロを定義する悪いテクニックです。

2)NOMINMAXコンパイラコマンドライン/ IDEで定義します。この決定の悪い点は、ソースを出荷する場合、ユーザーに同じことを行うよう警告する必要があることです。

3)使用する前に、コード内のマクロを単純に未定義にする

#undef min
#undef max

これはおそらく最もポータブルで柔軟なソリューションです。


2
オプション1のもう1つの問題は、単に機能するとは限らないことです。gdiplus.hなど、実際に必要な他のウィンドウヘッダーが他の場所に含まれている可能性があります。その場合、オプション3が唯一の希望かもしれません。
shawn1874 2014

27

私はまだWindowsヘッダーで時々問題を抱えており、NOMINMAXのプロジェクト全体の定義が常に機能するとは限りません。括弧を使用する代わりに、次のようにタイプを明示的にすることがあります。

int k = std::min<int>(3, 4);

これはまた、プリプロセッサがに一致するのを停止しmin、括弧による回避策よりも間違いなく読みやすくなります。


3
私は同意します、これは最良の解決策です。他の誰かが私に殴られたのを見たとき、私はちょうど別の答えを返すために戻ってきたところです。
PolyMesh 2016

16

次のようなものを試してください:

#define NOMINMAX
#include <windows.h>

デフォルトでは、WINDOWS.H定義minmaxマクロなど。それらが展開されると、std::min(たとえば)使用しようとするコードは、次のようになります。

int k = std::(x) < (y) ? (x) : (y);

エラーメッセージは、それstd::(x)が許可されていないことを示しています。


5

私の場合、プロジェクトには、windows.hまたはwindef.h明示的に含まれていませんでした。ブーストを使用していた。だから、私はプロジェクトProperties -> C/C++ -> Preprocessorに行きNOMINMAXPreprocessor Definitions(VS 2013、VS 2015)に追加することで問題を解決しました。


VS 2015の場合、ファイルでマクロを定義しても機能しませんでした。プロジェクトでの定義はうまくいきました。
qqqqq 2017年

3

windows.hを含む人々のために、影響を受けたヘッダーに以下を入れてください:

#include windows headers ...

pragma push_macro("min")
pragma push_macro("max")
#undef min
#undef max

#include headers expecting std::min/std::max ...

...

pragma pop_macro("min")
pragma pop_macro("max")

ソースファイルでは#undef minとmaxだけです。

#include windows headers ...

#undef min
#undef max

#include headers expecting std::min/std::max ...


2

この問題を解決するには、インクルードガードfix_minmax.h なしの名前のヘッダーファイルを作成するだけです

#ifdef max
    #undef max
#endif

#ifdef min
    #undef min
#endif

#ifdef MAX
    #undef MAX
#endif
#define MAX max

#ifdef MIN
   #undef MIN
#endif
#define MIN min

#include <algorithm>
using std::max;
using std::min;

基本的な使い方はこんな感じ。

// Annoying third party header with min/max macros
#include "microsoft-mega-api.h"
#include "fix_minmax.h"

このアプローチの長所は、あらゆる種類のインクルードファイルまたはコードの一部で機能することです。これにより、min/ maxマクロに依存するコードやライブラリを扱うときにも時間を節約できます


1

私はwindows.hがminをマクロとして定義していると思います、例えば

#define min(a,b)  ((a < b) ? a : b)

それはエラーメッセージを説明するでしょう。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.