tags:

views:

161

answers:

1

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?

+2  A: 

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!

Warren Young
I don't see what your template typedef adds beyond the original poster's suggestion. He's "polluted" things with shared_ptr<T>. You've polluted things with SharedPtr<T>::Type. Both seem equivalent, and his involves less typing.What does your template typedef accomplish beyond the using statement in the original post?
Rhys Ulerich
You hit on it: you no longer need to hoist these names out into the global namespace. My method doesn't necessarily add global names; you can namespace it if you like. And if you don't, mine is far less likely to conflict with names in another library.
Warren Young
Given that shared_ptr will eventually be in std:: and that autoconf can determine in which namespace shared_ptr is defined, I'm leaning towards "namespace std { using <somewhere>::shared_ptr;}" if there is no std::shared_ptr defined.
themis