Search code examples
c++c++11autoconf

How to use autoconf with C++0x features


What are the best practices for using autoconf in conjunction with shared_ptr and other TR1/BOOST C++0x templates so as to maximize portability and maintainability?

With autoconf I can determine whether shared_ptr is available as std::tr1::shared_ptr and/or boost::shared_ptr. Given that the same feature has two different names, I have the following questions:

  1. In the code, how should shared_ptr be referenced?
  2. Should std::tr1::shared_ptr be preferred over boost::shared_ptr?

For the first, the code is currently using preprocessor conditionals allowing non-qualified references to shared_ptr, a la

#if HAVE_STD_TR1_SHARED_PTR
using std::tr1::shared_ptr;
#elif HAVE_BOOST_SHARED_PTR
using boost::shared_ptr;
#else
#error "No definition for shared_ptr found"
#endif

Second, the code uses std::tr1:: over boost:: to minimize dependencies on external libraries (even if the the libraries are widely used).

Are these two solutions common? Are there better ones?


Solution

  • One improvement to your example code, and an answer to your first question, is to use the "template typedef" idiom:

    #if HAVE_STD_TR1_SHARED_PTR
        template <class T>
        struct SharedPtr {
            typedef std::tr1::shared_ptr<T> Type;
        };
    #elif HAVE_BOOST_SHARED_PTR
        template <class T>
        struct SharedPtr {
            typedef boost::shared_ptr<T> Type;
        };
    #else
    #   error "No definition for shared_ptr found"
    #endif
    
    // Declare a shared_ptr using our wrapper classes, saving us from having to care
    // where shared_ptr comes from:
    SharedPtr<int>::Type my_shared_int(new int(42));
    

    The main problem with this is the need to use the ::Type notation. It is purely because C++ currently has no way to have a typedef for a template. You can have a typedef for a template type instance, but it's important here that we retain genericity.

    As for whether you should prefer TR1 to Boost, I'd say yes. Now that compilers are shipping with partial C++0x support, I'd say you should also test for std::shared_ptr and prefer that to either of the others.

    You might need a fourth typedef if there are compilers that have a shared_ptr that's somewhere else. I don't know of such a compiler, but some C++ code I maintain does something similar to what you're asking about with the common slist extension to the Standard C++ Library, for singly-linked lists. Old g++ versions put it at global namespace, modern g++ puts it in the compiler-specific __gnu_cxx namespace, and we even found one that erroneously put it in std!