У меня есть заголовок и .cpp-файл (назовите его Foo.h/.cpp), который структурирован так (без лишних деталей для простоты):Поддержка различных версий boost в файлах .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;
}
проблема заключается в том, что теперь мне нужно поддерживать более ранняя версия 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()/definition существует только в более позднем сценарии ускоренной версии (два сценария не являются 100% конгруэнтными друг другу). Я знаю, что сама функция GetMessageIDToStringMap() никогда не понадобится для более раннего сценария ускоренной версии.
В идеале, я хотел бы оставить статический бимап внутри .cpp-файла и переместить GetMessageIDToStringMap() в другой файл где-нибудь, чтобы Foo.h/.cpp были на 100% конгруэнтными для каждого блока #ifdef. Проблема в том, что бимап является статической переменной внутри .cpp-файла, и ни один другой файл не может получить к нему доступ. Даже если я делаю bimap глобальной переменной вместо статической переменной, теперь мне нужно выставить глобальную переменную в файле заголовка, которая снова будет существовать только в более поздних версиях boost.
Есть ли способ решить эту проблему, чтобы две версии файла (boost> = 1.35 по сравнению с предыдущим повышением) всегда были на 100% конгруэнтными друг к другу, и все же функция GetMessageIDToStringMap() доступна в другом файле?
Глобальная переменная не должна отображаться в файле заголовка. вы можете использовать 'extern' в файле cpp. Я бы предпочел использовать классы singleton вместо globals или statics. – SHR
Вы имеете в виду добавить ключевое слово extern в bimap, определенную в .cpp? – Andrew