web-dev-qa-db-ja.com

Visual C ++のNOMINMAXで起こりうる問題

NOMINMAXをプログラムで他の何よりも先に定義すると、どのような問題が発生しますか?

私の知る限り、これにより_<Windows.h>_はminおよびmaxマクロを定義せず、STLとの多くの競合が発生します。 std::min()std::max()、またはstd::numeric_limits<T>::min()は解決されます。

Windows固有のレガシーコードのみに問題があるという前提で正しいのでしょうか。ほとんどすべてのライブラリは、マクロとして定義されているmin()およびmax()に依存するべきではありませんか?

編集:他のWindowsヘッダーに問題はありますか?

35
Manuel

NOMINMAXを使用することは、<windows.h>をインクルードするための唯一の完全ではない方法です。 UNICODESTRICTも定義する必要があります。後者は最近の実装ではデフォルトで定義されていますが。

ただし、Microsoftのヘッダーに問題が発生する可能性があります。 GdiPlusの場合。他の会社や個人のヘッダーの問題は知りません。

ヘッダーがGdiPlusのように名前空間を定義する場合、1つの修正は、関​​連するヘッダーのラッパーを作成することです。この場合、<algorithm>を含み、ヘッダーの名前空間内にusing namespace std;(またはusing std::min;およびusing std::max):

#define NOMINMAX
#include <algorithm>
namespace Gdiplus
{
  using std::min;
  using std::max;
}

これは、ヘッダーのグローバルスコープでのusing namespace std;とは大きく異なります。これはnever doにする必要があります。

名前空間がない場合の適切な回避策はわかりませんが、幸いにもそれに遭遇していないので、実際にはその特定の問題はおそらく疑わしいものです。

58

潜在的な副作用を制限するために、私は通常、次のようにNOMINMAXを使用します。

#define NOMINMAX
#include <windows.h>
#undef NOMINMAX

このようにして、NOMINMAXのスコープは比較的限定されます。

それは完璧な解決策ではありません。他にNOMINMAXがすでに定義されている場合、このパターンは失敗します(私はそのようなケースに遭遇したことはありません)。

本当に、本当に慎重になりたい場合は、#includeされたwindows.hがある場所に#includeラッパーヘッダーを含めることができます。ラッパーは次のようになります。

/* Include this file instead of including <windows.h> directly. */
#ifdef NOMINMAX
#include <windows.h>
#else
#define NOMINMAX
#include <windows.h>
#undef NOMINMAX
#endif

UNICODESTRICTを強制するなど、ラッパーで他のことを行うことも想像できます。

15
Adrian McCarthy

プリコンパイル済みヘッダー(stdafx.hなど)の場合、これを使用します。

#define NOMINMAX
#include <algorithm>
#include <Windows.h>
#ifndef min
#define min(x,y) ((x) < (y) ? (x) : (y))
#endif
#ifndef max
#define max(x,y) ((x) > (y) ? (x) : (y))
#endif
#include <gdiplus.h>
#undef min
#undef max
1
vladon

ヘッダーと名前空間を次の順序で宣言することで問題を修正しました。

#include <windows.h>
#include <minmax.h>
#include <gdiplus.h>

using namespace Gdiplus;
using namespace std;
0
Anil8753