在.h / .cpp文件中支持不同版本的boost

时间:2015-01-19 03:45:42

标签: c++ boost

我有一个标题和.cpp文件(称之为Foo.h / .cpp),其结构如下(为简单起见省略了几个不相关的细节):

foo.h中

#include <boost/bimap.hpp>

const std::string & ToHeader(const int msgID);
int ToMsgID(const std::string & msgHdr);

typedef boost::bimap<int, std::string> MsgIDBimap;
MsgIDBimap & GetMessageIDToStringMap();

Foo.cpp中

#include "Foo.h"
#include <boost/assign/list_of.hpp>

static MsgIDBimap msgIDBimap = boost::assign::list_of<MsgIDBimap::relation>
    ((int)ROM_MSG, "")
    ... // a whole bunch of other entries
; // end static bimap initialization

const std::string & ToHeader(const int msgID)
{
    MsgIDBimap::left_iterator foundIT = msgIDBimap.left.find(msgID);
    if(foundIT != msgIDBimap.left.end()) // found
    {
        return foundIT->second;
    }

    throw std::string("MSG_ID_NOT_FOUND");
}

int ToMsgID(const std::string & msgHdr)
{
    int msgID = (int)MSG_UNKNOWN; // unknown message header
    MsgIDBimap::right_iterator foundIT = msgIDBimap.right.find(msgHdr);
    if(foundIT != msgIDBimap.right.end()) // found
    {
        msgID = foundIT->second;
    }
    return msgID;
}

MsgIDBimap & GetMessageIdToStringMap()
{
    return msgIDBimap;
}

问题是现在我需要支持不支持bimap的早期版本的boost(很糟糕,我知道......但我别无选择)。到目前为止,这是我的解决方案:

foo.h中

#include <boost/version.hpp>
#define BOOST_VER_MAJOR (BOOST_VERSION/100000)        // ex.: 1   in  1_37_0
#define BOOST_VER_MINOR ((BOOST_VERSION/100) % 1000)  // ex.: 37  in  1_37_0
#define BOOST_VER_PATCH (BOOST_VERSION % 100)         // ex.: 0   in  1_37_0

/*************************************************************************************************/
#if ((BOOST_VER_MAJOR >= 1) && (BOOST_VER_MINOR >= 35)) // boost greater than or equal to 1.35 (bimap available)
#include <boost/bimap.hpp>
#endif
/*************************************************************************************************/

const std::string & ToHeader(const int msgID);
int ToMsgID(const std::string & msgHdr);

/*************************************************************************************************/
#if ((BOOST_VER_MAJOR >= 1) && (BOOST_VER_MINOR >= 35)) // boost greater than or equal to 1.35 (bimap available)
typedef boost::bimap<int, std::string> MsgIDBimap;
MsgIDBimap & GetMessageIdToStringMap();
#endif
/*************************************************************************************************/

Foo.cpp中

#include "Foo.h"
#include <boost/assign/list_of.hpp>

#if ((BOOST_VER_MAJOR >= 1) && (BOOST_VER_MINOR >= 35)) // boost greater than or equal to 1.35 (bimap available)

static MsgIDBimap msgIDBimap = boost::assign::list_of<MsgIDBimap::relation>
    ((int)ROM_MSG,            "") // <ROM message> (no header)

; // end static msgIDBimap initialization

const std::string & ToHeader(const int msgID)
{
    MsgIDBimap::left_iterator foundIT = msgIDBimap.left.find(msgID);
    if(foundIT != msgIDBimap.left.end()) // found
    {
        return foundIT->second;
    }

    throw std::string("MSG_ID_NOT_FOUND");
}

int ToMsgID(const std::string & msgHdr)
{
    int msgID = (int)MSG_UNKNOWN; // unknown message header
    MsgIDBimap::right_iterator foundIT = msgIDBimap.right.find(msgHdr);
    if(foundIT != msgIDBimap.right.end()) // found
    {
        msgID = foundIT->second;
    }
    return msgID;
}

MsgIDBimap & GetMessageIdToStringMap()
{
    return msgIDBimap;
}

/*************************************************************************************************/
#else // boost less than 1.35, bimap not available

typedef std::map<int, std::string> MsgIDToStringMap;
static MsgIDToStringMap msgIDToStringMap = boost::assign::map_list_of<int, std::string>
    ((int)ROM_MSG,            "") // <ROM message> (no header)
; // end static msgIDToStringMap initialization

const std::string & ToHeader(const int msgID)
{
    const MsgIDToStringMap::const_iterator foundIT = msgIDToStringMap.find(msgID);
    if(foundIT != msgIDToStringMap.end()) // found
    {
        return foundIT->second;
    }

    throw std::string("MSG_ID_NOT_FOUND");
}

#define FLIP_ARGS(x,y) (y,x)
typedef std::map<std::string, int> StringToMsgIDMap;
static StringToMsgIDMap stringToMsgIDMap = boost::assign::map_list_of<std::string, int>
    FLIP_ARGS((int)ROM_MSG,            "") // <ROM message> (no header)

; // end static stringToMsgIDMap initialization

int ToMsgID(const std::string & msgHdr)
{
    int msgID = (int)MSG_UNKNOWN; // unknown message header
    const StringToMsgIDMap::const_iterator foundIT = stringToMsgIDMap.find(msgHdr);
    if(foundIT != stringToMsgIDMap.end()) // found
    {
        msgID = foundIT->second;
    }
    return msgID;
}
#endif

虽然这有效,但问题是GetMessageIDToStringMap()函数声明/定义仅存在于后面的升级版本场景中(两个场景彼此不是100%一致)。我知道早期的升级版本场景不会需要GetMessageIDToStringMap()函数本身。

理想情况下,我想将静态bimap保留在.cpp文件中,并将GetMessageIDToStringMap()移动到某个地方,以便Foo.h / .cpp对每个#ifdef块100%一致。问题是bimap是.cpp文件中的静态变量,没有其他文件可以访问它。即使我将bimap设为全局变量而不是静态变量,我现在必须在头文件中公开一个全局变量,这个变量只会出现在更高版本的boost中。

有没有办法解决这个问题,以便文件的两个版本(boost&gt; = 1.35与之前的boost相比)总是100%相互一致,但GetMessageIDToStringMap()函数在另一个文件中可用?

1 个答案:

答案 0 :(得分:0)

回应问题中的评论:

在foo.cpp中:

typedef std::map<int, std::string> MsgIDToStringMap;
//you can remove the static
MsgIDToStringMap msgIDToStringMap = ...

现在在other.cpp文件中:

extern MsgIDToStringMap msgIDToStringMap;
//and you can use the global variable.

但正如我在第一条评论中所说的,我更喜欢单身课程。