我目前正在编写一个C ++库,需要使用GCC for Linux和Sun CC for Solaris进行编译。为了性能,我创建了一些基于编译器选择不同头的类; GCC使用c ++ 0x或TR1或使用niether和Sun CC RogueWave或STLPort。我正在努力找出#ifdef类型定义的最佳方法,例如:
namespace project {
#if defined(__GNUG__)
#if defined(HAVE_CXXOX)
#include <unorderd_map>
typedef srd::unordered_map map;
#elif defined(HAVE_TR1)
#include <tr1/unordered_map>
typedef std::tr1::unordered_map map;
#else
#include <map>
typedef std::map map;
#endif
#elif defined(__SUNPROC_CC)
#include <map>
typedef std::map map;
#endif
} //namespaces
答案 0 :(得分:3)
这不会有两个原因:
namespace project { ... }
范围之外。 (如果标题只包含模板和内联函数,它可能无论如何都可以工作,但我不会指望它。)typedef
不适用于模板。您可以在其中定义一个空的派生类。所以也许是这样的:
#if defined(__GNUG__)
#if defined(HAVE_CXXOX)
#include <unordered_map>
#define MAP std::unordered_map
#elif defined(HAVE_TR1)
#include <tr1/unordered_map>
#define MAP std::tr1::unordered_map
#else
#include <map>
#define MAP std::map
#endif
#elif defined(__SUNPROC_CC)
#include <map>
#define MAP std::map
#endif
namespace myproject {
template <class K, class V>
class map : public MAP<K, V> {};
}
#undef MAP
答案 1 :(得分:0)
在进一步阅读之后,可能值得研究C ++ 0x中新的“模板别名”概念。这里有一些未经测试的代码作为它如何工作的一个例子。
#if defined(__GNUG__)
#if defined(HAVE_CXXOX)
#include <unordered_map>
#define MAP std::unordered_map
#elif defined(HAVE_TR1)
#include <tr1/unordered_map>
#define MAP std::tr1::unordered_map
#else
#include <map>
#define MAP std::map
#endif
#elif defined(__SUNPROC_CC)
#include <map>
#define MAP std::map
#endif
namespace internal {
template <typename K, typename V>
struct unordered_map { typedef MAP<K, V>; >;
} //internal
template <typename K, typename V>
using unordered_map = typename internal::unordered_map<K, V>::type;
有关详情,请参阅此处http://www2.research.att.com/~bs/C++0xFAQ.html#template-alias
答案 2 :(得分:0)
在定义和包含的棘手之间以及测试几乎每个编译器的必要性,更不用说次要版本和东西(例如:tuple_element
在某些特定版本的GCC中具有其他名称的东西),我采取了理智的方法:将解决方案委托给实际拥有选择权和实施权的人。这意味着使用像Boost.TR1这样的包装器或者“自己动手”。
我假设标题路径与C ++ 11类似,就像在#include <header>
中一样编写代码。用户比我更了解他自己的环境,因此他将能够例如:add Boost.TR1 to the include paths(或他选择的另一个TR1实现)使事情更加无缝地工作。哎呀,即使只是指向一个带有“重定向”标题的文件夹,如果需要,它只会转发到<tr1/*>
版本。等等。基本上,如果开发人员已经为你做出了牺牲,为什么要自己经历宏观噩梦呢?
这让我背上了很多痛苦,因为它允许我编写“一次编写”代码,而不必每次都测试不同的编译器,即使是次要版本,也有助于使我的代码向前兼容C ++ 11
当然,它有一些技巧 - 取决于你对你的编译器有什么假设,你可能需要使用像“using namespace tr1
”黑客或(更好)交替等其他技巧同类