Microsoft Windowsプラットフォームのヘッダファイル windows.h は悪名高いmin
, max
マクロを定義するため、プリプロセス時に意図せずmin
やmax
が置換されてしまい、妙なコンパイルエラーを引き起こす場合がある。一例としてMSVC10で下記コードをコンパイルすると、それぞれエラーメッセージが出力される。
#include <windows.h> #include <numeric> //-------- Case 1 int a = 1, b = 2; int x = std::min(a, b); // error C2589: '(' : スコープ解決演算子 (::) の右側にあるトークンは使えません。 // error C2059: 構文エラー : '::' //-------- Case 2 double maxvalue = std::numeric_limits<double>::max(); // warning C4003: マクロ 'max' に指定された実引数の数が少なすぎます。 // error C2589: '(' : スコープ解決演算子 (::) の右側にあるトークンは使えません。 // error C2059: 構文エラー : '::'
回避策1:マクロ定義を行なわせない
ヘッダファイル windows.h の include より前に、マクロNOMINMAX
を定義しておく。Microsoft KBで公開されている正攻法。
#define NOMINMAX #include <windows.h>
回避策2:マクロ定義を無効化する
ユーザが明示的にマクロの undef を行う。
#include <windows.h> #undef min #undef max
回避策3:プリプロセッサによるマクロ展開を抑止する(1)
min
やmax
を含む式を括弧でくくり*1、関数形式マクロ(function-like macro)として扱われないようにする。
//-------- Case 1 int x = (std::min)(a, b); // OK //-------- Case 2 double maxvalue = (std::numeric_limits<double>::max)(); // OK
回避策4:プリプロセッサによるマクロ展開を抑止する(2)
Boost.Config提供のマクロBOOST_PREVENT_MACRO_SUBSTITUTION
をmin
やmax
の直後に配置し、関数形式マクロとして扱われないようにする。
#include <boost/config.hpp> //-------- Case 1 int x = std::min BOOST_PREVENT_MACRO_SUBSTITUTION (a, b); // OK //-------- Case 2 double maxvalue = std::numeric_limits<double>::max BOOST_PREVENT_MACRO_SUBSTITUTION (); // OK
Boost Library Requirements and Guidelines によると、同マクロは (1) min
/max
を名前空間を指定せずADL経由で呼び出したいとき、または (2) クラスメンバ関数名としてmin
/max
を宣言定義するときに用いる。