Boost logo

Boost :

From: William E. Kempf (wekempf_at_[hidden])
Date: 2003-01-09 10:14:36


OK, I've been thinking about the issue of conditional compilation brought up by the boost::thread proposal. I see to complaints involved with conditional compilation, as used there:

1) It's generally agreed that the PP should be avoided because it doesn't respect namespace boundaries (among other things).

2) It's hard to consider something "portable" if it relies on conditional compilation.

Let me try to address both, and suggest some alternative implementations.

First, there's not much risk for problems with using the PP here, since few macros are defined, and those that are are specifically named to avoid potential name clashes. But we could eliminate the PP here using some metaprogramming techniques.

Instead of #define symbols, you'd instead use typedefs for yes_type and no_type. Most cases where you'd do conditional compilation could then be replaced with calls to:

template <typename OptionTag>
bool option_available()
{
}

where specializations turn yes_type and no_type into the equivalent runtime boolean values. Code like this:

if (option_available<thread::attributes::stack_size_option>())
{
   // do stuff
}

would likely be entirely optimized out when the option isn't available. (This does mean the optional functions still need to exist in order for the code to compile... but this helps us later.)

There are a few cases where this simple function call won't work, such as when defining the data members available in a class based on available options... but you can use PTS techniques in a case specific manner for most of the cases I can imagine. (Maybe somebody even has a clever way to handle things like this with library code instead of the less user friendly PTS techniques?)

One thing this doesn't address is when an application/library simply can't handle situations where an option is not available. But this can be handled with another function:

template <typename OptionTag>
void require_option()

Which results in a compile time assertion when the specified option isn't available. (This is off the top of my head, and it may well be that there's a better solution than using a function template, such as using a class template, which would be allowed in more places.)

Now to address the second isssue. It is true that the perception is that this makes a library less "portable". However, there are things which are available on many, but not all, platforms, and it's still beneficial to have a standard on those platforms where it is available. Boost.Threads itself is such an example. Not all platforms that C++ targets will have threading capabilities. So you DO (IMHO) need a way to have a standardized interface for those platforms where it can be done, and provide the needed mechanisms for the compiler and programmer to deal with platforms where it's not available.

Simply using a runtime check seems like the wrong idea to me. It puts off detecting the problem when there's no reason to do so. However, I can see cases in which you can put this off, and doing so is beneficial. The above approach allows this... if a function is not supported it would still have to be implemented in order for the compiler to not complain, and the implementation can simply throw an appropriate exception on platforms where it's not supported. This allows the developer to choose either compile time or runtime solutions to this case.

Thoughts, comments?

William E. Kempf
wekempf_at_[hidden]


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk