【C++】windows.hインクルード時のmax,min関数エラーを回避する方法

C++でWin32デスクトップアプリケーション開発する際に、windows.hをインクルードすることになりますが、このwindows.hの影響でコンパイルエラーが発生してしまう関数があります。

それがC++の標準ライブラリに定義されているmax関数とmin関数です。

例えば以下のコードを見てみましょう。

 
#include <algorithm>
int main()
{
        int a = 10;
        int b = 20;
        int v1 = std::min(a, b);
        int v2 = std::max(a, b);
}
クリップボードにコピーする

こちらのコードは何も問題なくコンパイルが通り実行も可能です。

ですが、先ほどのプログラムにwindows.hをインクルードした場合はどうなるでしょうか?

 
#include <algorithm>
#include <Windows.h>
int main()
{
        int a = 10;
        int b = 20;
        int v1 = std::min(a, b);
        int v2 = std::max(a, b);
}
クリップボードにコピーする

こちらはコンパイルエラーになります。

実際に実行すると(‘: スコープ解決演算子 (::) の右側にあるトークンは使えません。.構文エラー: ‘)’などがたくさん表示されたかと思います。

Windows.hのインクルードをやめれば解決しますが、そういうわけにもいかないので、max,min関数がコンパイルエラーにならないようにwindows.hをインクルードする方法を解説していきます。

windows.hのインクルードでコンパイルエラーになる理由

windows.hにmaxマクロ関数とminマクロ関数が定義されていることが原因です。

試しにネームスペースのstdを外した状態でコンパイルしてみましょう。

 
#include <algorithm>
#include <Windows.h>
int main()
{
        int a = 10;
        int b = 20;
        int v1 = min(a, b);
        int v2 = max(a, b);
}
クリップボードにコピーする

すると何事もなかったかのようにコンパイルが通り実行できるはずです。

このマクロ関数がC++標準ライブラリ(STL)のmax関数とmin関数を上書きしてしまっているために、コンパイルが通らなくなってしまってしまうのです。

max関数・min関数エラーの回避方法

windows.hによるエラーを回避する方法は3つあります。

探せば他にあるかもしれませんが、どれか一つ知っておけば問題ありません。

windows.hインクルード前にNOMINMAXマクロを定義する

一番簡単な方法がNOMINMAXマクロを定義する方法です。

NOMINMAXマクロを定義したあとにwindows.hをインクルードすると、minマクロ関数・maxマクロ関数がそれぞれ定義されなくなり、標準ライブラリのmin,max関数を使ってもコンパイルエラーにならなくなります。

 
#include <algorithm>
#define NOMINMAX
#include <Windows.h>
int main()
{
        int a = 10;
        int b = 20;
        int v1 = std::min(a, b);
        int v2 = std::max(a, b);
}
クリップボードにコピーする

NOMINMAXは全て大文字ですので、間違えないようにしてください。

この方法が一番シンプルかつ簡単な方法ですのでおすすめです。

undefでマクロ定義を無効化する

undefで定義済みのマクロを無効化することでも、コンパイルエラーを回避できます。

 
#include <algorithm>
#include <Windows.h>
#undef min
#undef max
int main()
{
        int a = 10;
        int b = 20;
        int v1 = std::min(a, b);
        int v2 = std::max(a, b);
}
クリップボードにコピーする

一つ目の方法と比べるとやや面倒ですが、こういう方法もあるということを覚えておくといいかもしれません。

標準ライブラリの関数を優先させる

少しトリッキーな方法ではありますが、関数名をカッコで囲うことでSTLのmax関数・min関数を優先させることができます。

 
#include <algorithm>
#include <Windows.h>
int main()
{
        int a = 10;
        int b = 20;
        int v1 = (std::min)(a, b);
        int v2 = (std::max)(a, b);
}
クリップボードにコピーする

できるとは言っても少し変わった書き方になってしまいますし、全てのmin,max関数をこのように書かないといけなくなるのであまりお勧めはしません。

基本的にはNOMINMAX

特に理由がなければ、NOMINMAXマクロを定義してコンパイルエラーを回避する方法を取りましょう。

この方法は一番行数を減らせるので、無駄な行動を削減できます。

ですので、基本的にはwindows.hをインクルードする前にNOMINMAXマクロの定義する方法で対策するようにしてください。

【ピックアップ】C++プログラマ必読書

おすすめ度 5
対象読者 C++でHello Worldプログラムを書いたことがあるレベル~
読破して得られるもの 実用レベルのC言語・C++スキル習得

C++プログラマを目指す方なら必ず読んでおきたい一冊です。

ただただ関数の使い方を学ぶだけではちゃんとしたソフトウェア開発することは困難です。ですがこの参考書は、外部ライブラリを組み込んでチャットボットを作成するといった、実用レベルのスキルを身につけることができます。

よくあるプログラミング入門書だと、文法やかんたんな関数の紹介、ファイルを操作するだけで終わっていることが少なくありません。

こちらの一冊は基礎から応用までたくさんのことが解説されているため、とんでもない大ボリュームですが、この参考書読破できた頃にはソフトウェアの開発ができる実用レベルのC++スキルが習得できているでしょう。

コメント

タイトルとURLをコピーしました