1. 程式人生 > >C++跨平臺系列:解決STL的max()與numeric_limits::max()和VC6 min/max 巨集衝突問題

C++跨平臺系列:解決STL的max()與numeric_limits::max()和VC6 min/max 巨集衝突問題

多年以前,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]

     [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 巨集命令騙去

相關推薦

C++跨平臺系列解決STL的max()numeric_limits::max()VC6 min/max 巨集衝突問題

多年以前,Microsoft 幹了一件比 #define N 3 還要蠢的蠢事,那就是在 <windows.h> 放入了 min/max 這兩個巨集命令(macros)。      #define max(a,b)            (((a) >

目標定位檢測系列交併比(IOU)非極大值抑制(NMS)的pythonC/C++實現

Python實現 交併比(Intersection over Union)和非極大值抑制是(Non-Maximum Suppression)是目標檢測任務中非常重要的兩個概念。例如在用訓練好的模型進行測試時,網路會預測出一系列的候選框。這時候我們會用NMS來移除一些多餘的候選框。即移除一些IOU

c#學習系列之委托事件

gen () 第一次用 關鍵字 將在 generic frame 再次 body 1. 引言 委托 和 事件在 .Net Framework中的應用非常廣泛,然而,較好地理解委托和事件對很多接觸C#時間不長的人來說並不容易。它們就像是一道檻兒,過了這個檻的人,覺得真是太容易

C#強化系列HttpModule,HttpHandler,HttpHandlerFactory簡單使用

判斷 response exec 例子 所有 pri 需要 系統默認 return 這三個對象我們在開發Asp.net程序時經常會用到,似乎很熟悉,但有時候又不太確定。本文通過一個簡單的例子來直觀的比較一下這三個對象的使用。HttpModule:Http模塊,可以在頁面處理

C++解析(20)智慧指標型別轉換函式

0.目錄 1.智慧指標 2.轉換建構函式 3.型別轉換函式 4.小結 1.智慧指標 記憶體洩漏(臭名昭著的Bug): 動態申請堆空間,用完後不歸還 C++語言中沒有垃圾回收機制 指標無法控制所指堆空間的生命週期 我們需要什麼: 需要一個特殊的指標 指標生命週期結束

C++解析(23)多型C++物件模型

0.目錄 1.多型 2.C++物件模型 3.繼承物件模型 4.多型物件模型 5.小結 1.多型 面向物件中期望的行為: 根據實際的物件型別判斷如何呼叫重寫函式 父類指標(引用)指向 父類物件則呼叫父類中定義的函式 子類物件則呼叫子類中定義的重寫函式

C++解析(26)函式模板類模板

0.目錄 1.函式模板 1.1 函式模板與泛型程式設計 1.2 多引數函式模板 1.3 函式過載遇上函式模板 2.類模板 2.1 類模板 2.2 多引數類模板與特化 2.3 特化的深度分析 3.小結 1.函式模板 1.1 函式模板與泛型程式設計 C++中有幾

C\C++程式設計中相對路徑絕對路徑

在程式設計的過程中,會遇到需要引用外部檔案的情況,有兩種路徑的書寫方式,通過下面的列子進行分析。 電腦硬碟E盤下,建資料夾“test”,"test"下建立子資料夾“file”,"file"下建子資料夾“data”,電腦資源管理器顯示目錄 E:\test\fi

新建VS工程填坑解決方案專案不在同一目錄

A.新建專案->空工程 B.新增依賴庫 1、屬性->C/C++->附加包含目錄 注:新增標頭檔案目錄,必須指向子資料夾 2、屬性->連結器->常規->附加庫目錄 注:新增exp和lib(輸出庫檔案、輸入庫檔案)的目錄 3、屬性->連結器->輸入-&g

C#基礎系列Attribute特性使用

前言:總結了下反射得基礎用法,這章我們來看看C#的另一個基礎技術——特性。 1、什麼是特性:就博主的理解,特性就是在類的類名稱、屬性、方法等上面加一個標記,使這些類、屬性、方法等具有某些統一的特徵,從而達到某些特殊的需要。比如:方法的異常捕捉,你是否還在某些可能出現

C#基礎系列非同步程式設計初探asyncawait

前言:前面有篇從應用層面上面介紹了下多執行緒的幾種用法,有博友就說到了async, await等新語法。確實,沒有非同步的多執行緒是單調的、乏味的,async和await是出現在C#5.0之後,它的出現給了非同步並行變成帶來了很大的方便。非同步程式設計涉及到的東西還

C#基礎系列序列化效率比拼

      前言:作為開發人員,物件的序列化恐怕難以避免。樓主也是很早以前就接觸過序列化,可是理解都不太深刻,對於用哪種方式去做序列化更是隨波逐流——專案中原來用的什麼方式照著用就好了。可是這麼多年自己對於這東西還是挺模糊的,今天正好有時間,就將原來用過的幾種方式總結了下,也算是做一個記錄,順便做了下效能測

C#基礎系列反射筆記

前言:使用反射也有幾年了,但是一直覺得,反這個概念很抽象,今天有時間就來總結下這個知識點。 1、為什麼需要反射: 最初使用反射的時候,作為小菜總是不理解,既然可以通過new 一個物件的方式得到物件,然後通過物件去呼叫屬性和方法,那麼為什麼還需要反射去呼叫呢?後來使用

C#基礎系列委託實現簡單設計模式(1)

前言:這篇簡單介紹下委託的使用。當然啦,園子裡面很多介紹委託的文章都會說道:委託和事件的概念就像一道坎,過了這個檻的人,覺得真是太容易了,而沒有過去的人每次見到委託和事件就覺得心裡發慌。確實這東西就像最開始學C語言的指標一樣,令人有一種很糾結的感覺,總覺得要呼叫一個

C#基礎系列委託設計模式(2)

前言:這篇打算從設計模式的角度去解析下委託的使用。我們知道使用委託可以實現物件行為(方法)的動態繫結,從而提高設計的靈活性。上次說過,方法可以理解為委託的例項,站在方法的層面,委託例項的一個非常有用的特性是它既不知道,也不關心其封裝方法所屬類的詳細資訊,對它來說最重

C#基礎系列再也不用擔心面試官問我“事件”了

前言:作為.Net攻城獅,你面試過程中是否遇到過這樣的問題呢:什麼是事件?事件和委託的區別?既然事件作為一種特殊的委託,那麼它的優勢如何體現?諸如此類…你是否也曾經被問到過?你又是否都答出來了呢? 關於面試中涉及到的事件的問題,我們只需要抓住幾個關鍵點就好了: (1

C#基礎系列小話泛型

前言:這一章來總結下C#泛型技術的使用。據博主的使用經歷,覺得泛型也是為了重用而生的,並且大部分時候會和反射一起使用。這次還是打算圍繞WWH(即What、Why、How)來講解。 1、什麼是泛型:通過引數化型別來實現在同一份程式碼上操作多種資料型別。利用“引數化型別

C#基礎系列擴充套件方法的使用

前言:打算分三個層面來介紹這個知識點,分別是:.Net內建物件的擴充套件方法、一般物件的擴充套件方法、泛型物件的擴充套件方法。 什麼是擴充套件方法?回答這個問題之前,先看看我們一般情況下方法的呼叫。類似這樣的通用方法你一定寫過:

C#基礎系列Linq to Xml讀寫xml

前言:xml的操作方式有多種,但要論使用頻繁程度,博主用得最多的還是Linq to xml的方式,覺得它使用起來很方便,就用那麼幾個方法就能完成簡單xml的讀寫。之前做的一個專案有一個很變態的需求:C#專案呼叫不知道是什麼語言寫的一個WebService,然後新增服

C#基礎系列多執行緒的常見用法詳解

前言:此篇就主要從博主使用過的幾種多執行緒的用法從應用層面大概介紹下。文中觀點都是博主個人的理解,如果有不對的地方望大家指正~~ 1、多執行緒:使用多個處理控制代碼同時對多個任務進行控制處理的一種技術。據博主的理解,多執行緒就是該應用的主執行緒任命其他多個執行緒去協