2011年9月26日 星期一

Boost 神秘的 deprecated warning

Boost 是一個相當強大好用的 C++ library,一直都沒辦法把它摸透。最近在用的時候遇到神秘的問題,追了一下還是沒辦法完全理解,先筆記下來也許會有什麼進展(或是得到有緣人的提點:P)。

首先是我的開發環境:Ubuntu 10.04 64-bits, GCC 4.4.3, Boost 1.40 (libboost-dev 1.40.0.1)

我其實是在
#include <boost/graph/adjacency_list.hpp>
的地方遇到問題的,他出現的 warning message 如下:
warning: #warning This file includes at least one deprecated or antiquated header which may be removed without further notice at a future date. Please use a non-deprecated interface with equivalent functionality instead. For a listing of replacement headers and interfaces, consult the file backward_warning.h. To disable this warning use -Wno-deprecated.

這訊息事實上是在
<backward/backward_warning.h>
這個檔案裡寫死的,至於為什麼會出現這個訊息呢?是因為 <boost/graph/adjacency_list.hpp> 使用了 <backward/hash_set> 這個檔案,他不被建議使用....(deprecated)。相信 boost 會使用 <hash_set> 也是歷史的塵埃吧?根據該 warning 檔案裡面的敘述,建議使用 <unordered_set> 取代 <hash_set>,以上是關於這個部份的發現。

另一方面,boost 本身有相關的設定可以做,尋找的開端是 <boost/config.hpp>,從它開始追可以追蹤到 <boost/config/suffix.hpp> 這個檔案,在我這個版本的 298 行有這樣的一段程式碼:

#if defined(BOOST_HAS_HASH) && !defined(BOOST_HASH_SET_HEADER)
#  define BOOST_HASH_SET_HEADER <hash_set>
#endif
網路上找到的這個解答也是說明可以藉由 define BOOST_NO_HASH 來 disable hash 的支援...但是相對來說,就無法在 adjacency_list 中使用 hash_setS 或是 hash_mapS 了。

實際嘗試過後,define BOOST_NO_HASH 的確可以避免該 warning message 的產生,但是這明顯不是最好的作法,所以我嘗試在 boost 相關的 inclusion 之前先這麼做:
#define BOOST_HASH_SET_HEADER <unordered_set>
這麼做是來自於 <boost/graph/adjacency_list.hpp> 中的第20行(一樣是在我的版本):
// TODO: Deprecating this requires some cooperation from Boost.Config. It's not
// a good idea to just refuse the inclusion because it could break otherwise
// functioning code.
#if !defined BOOST_NO_HASH
#    ifdef BOOST_HASH_SET_HEADER
#        include BOOST_HASH_SET_HEADER
#    else
#        include <hash_set>
#     endif
#endif
想像中的一切是多麼完美......只要我 define 了 BOOST_HASH_SET_HEADER,那他就不會去 include 那討厭的 <hash_set>,而是使用我要他 include 的 <unorder_set> 了!然而天不從人願(好爛的轉折語= =),即使我這麼做:
#define BOOST_HASH_SET_HEADER <unordered_set>
似乎還是會被 <boost/config.hpp>給改回來= =a
最神奇的是我找不到他在哪裡改的XD

我自己的引用方式如下:
#define BOOST_HASH_SET_HEADER <unordered_set>
#include <boost/bind.hpp>
#include <boost/graph/adjacency_list.hpp>
那個 bind.hpp 會 include config.hpp :(

如果這麼做:
#include <boost/bind.hpp>
#define BOOST_HASH_SET_HEADER <unordered_set>
#include <boost/graph/adjacency_list.hpp>
 會造成 BOOST_HASH_SET_HEADER 的重複定義,因為 config.hpp 裡面呼叫 suffix.hpp 會去 define 這玩意兒....好吧,那就只好來硬的:
#include <boost/bind.hpp>
#undef BOOST_HASH_SET_HEADER
#define BOOST_HASH_SET_HEADER <unordered_set>
#include <boost/graph/adjacency_list.hpp>
結果噴出來的訊息我也只能心服口服了.....
error: #error This file requires compiler and library support for the upcoming ISO C++ standard, C++0x. This support is currently experimental, and must be enabled with the -std=c++0x or -std=gnu++0x compiler options.
這個訊息來自 <unordered_set>......要用 C++0x 是吧.......所以說,我.........放棄了= =a

目前暫時的結論就是,先 define BOOST_NO_HASH 吧,等到 boost (或是說 BGL?) 出了新版,還有 GCC 預設支援 C++0x 的時候,這問題應該連改都不用改就解決了XD"

有興趣的朋友們可以嘗試看看強迫使用 C++0x 配合 <unordered_set> 看看會不會順利編譯唷 :D

PS. 歡迎把你的經驗分享給我 :P

沒有留言:

張貼留言