http://www.cnblogs.com/cvbnm/articles/1947743.html
多年以前,Microsoft 幹了一件比 #define N 3
還要蠢的蠢事,那就是在 <windows.h>
放入了 min
/max
這兩個宏命令(macros)。
#define max(a,b) (((a) > (b)) ? (a) : (b))
因此,我們沒辦法好好地使用 C++ Standard 的 min/max 這兩個 algorithms,也沒有辦法好好地使用 numeric_limits<>
。前者 Microsoft 用了另外兩個宏命令,_MIN
與 _MAX
來補救,但考量到跨平台程式設計,這兩個 macros 有跟沒有一樣。
#define _MAX _cpp_max ——> const T& std::_cpp_max(const T&,const T&);
後者就真的很傷腦筋了,很多時候,numeric_limits<>
的使用是無法避免的[1],
[]舉例來說,為了跨平台的需求,我們無法得知 size_t
的真正型別,故無法直接使用 C 的 UINT_MAX
來表現 size_t
的最大可能值。最好的方法,當然還是使用 numeric_limits<size_t>::max()
。
但當直接或間接 #include
進 <windows.h>
的時候,VC6 就會出現 C4003 warning 然後後面的程式就爛掉了。
通常來說,碰到這種相容性問題,先找看看 Boost 怎麼作就對了。(因為 Boost 裡面充滿了各種各樣最先進的 C++ 技術,而先進的 C++ 技術通常都會碰到相容性問題,因此 Boost 裡面就會有比較合適的解法存在。)於是我在 boost/config/suffix.hpp
裡,發現了 BOOST_PREVENT_MACRO_SUBSTITUTION
這一個宏命令,被安插在可能被 VC6 搞爛的 min
/max
後面,括弧前面。其用法如下:
std::max BOOST_PREVENT_MACRO_SUBSTITUTION(value1, value2);
// or
std::numeric_limits<Foo>::max BOOST_PREVENT_MACRO_SUBSTITUTION();
實際上,BOOST_PREVENT_MACRO_SUBSTITUTION
是空的,會被代換成沒有任何東西,其目的應該是為了騙過 preprocessor,使其認為 min
/max
不是 VC6 雞婆定義的那個 macro,而留給 compiler 來剖析之。
不過,照著這招做實驗後發現,沒有用。也許是 Boost 還有其他機制,讓這招成功,但總之我就是弄不出來,BOOST_PREVENT_MACRO_SUBSTITUTION
會先被 preprocessor 代換成沒有任何東西,然後原來的 min
/max
的問題就又出現了。
只好求助 Google,幸好讓我發現了這串討論:《problems with new boost lib》,裡面提到可以使用括弧,來避免 preprocessor 作怪。也就是說,程式改成這麼寫:
(std::max)(value1, value2);
// or
(std::numeric_limits<Foo>::max)();
把 min
/max
連同前面的 namespace 括弧刮起來,再接上呼叫用的 (),這樣就既是合法的 C++ 語法,又可以避免愚鈍的 preprocessor 被白爛 VC6 的 min
/max
宏命令騙去。