开发者

Macro-based selection of C++ headers

I am currently writing a C++ library which will be required to compile with both GCC for linux and Sun CC for Solaris. In the interest of performance I am creating some classes which select different headers based on compiler; GCC with c++0x or TR1 or with niether and Sun CC RogueWave or STLPort. I'm sturggling to work out the best means of #ifdef'ing the typedefs, for example:

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 ma开发者_JAVA技巧p;
        #endif
    #elif defined(__SUNPROC_CC)
        #include <map>
        typedef std::map map;
    #endif

} //namespaces


This won't work for two reasons:

  1. Headers must be included outside of the scope of namespace project { ... }. (If the header contains nothing but templates and inline functions, it might work anyway, but I wouldn't count on it.)
  2. typedef doesn't work on templates. There's a workaround where you define an empty derived class.

So perhaps something like this:

#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


After some further reading it might be worthwhile investigatinng the new 'template alias' concept in C++0x. here is some untested code as an example of how it would work.

#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;

See here for more information http://www2.research.att.com/~bs/C++0xFAQ.html#template-alias


Between the thornyard of defines and includes and the necessity to test for pretty much every single compiler not to mention minor versions and stuff (things like eg.: tuple_element having another name in some specific versions of GCC), I took the sane approach: delegate the solution to the people who actually have the choice and power to implement it. That means either using a wrapper like Boost.TR1 or "do it yourself".

I code most stuff under the assumption that header paths are like in C++11, as in #include <header>. The user knows his own environment better than I do and thus he'll be able to eg.: add Boost.TR1 to the include paths (or another TR1 implementation of his choosing) to make things work much more seamlessly. Heck, even just point to a folder with "redirect" headers that just forward to the <tr1/*> versions if desired. Etcetera. Essentially, why go through macro nightmares yourself if developers have already made that sacrifice for you?

This has taken a lot of pains off my back because it allows me to write "write-once" code, without having to test for different compilers even in minor versions each time, and also helps make my code forwards-compatible to C++11.

Of course, there is some trickery to it though - depending on what can you assume about your compiler(s), you might need to use tricks like the "using namespace tr1" hack or (better) an alternand others of its kind

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜