|
Boost : |
From: Ed Brey (brey_at_[hidden])
Date: 1999-07-02 07:34:15
Email seemed somewhat boring, until Dietmar Kuehl wrote:
>
>The more interesting part in this is, how to exactly handle platform
>specific stuff? Macros come to mind but isn't there something better?
>I can imagine that eg. templates could also be used and might be more
>convenient. A general approach for this would a great contribution,
>IMO.
The C++ standard provides a good example of just such a generic
approach: allocators. They allow generic routines to work with
platform-specific memory allocation schemes. On a different thread
on this mailing list, I proposed breaking up the generic and platform-
specific parts of timer using the same kind of scheme.
The generic code lives in one .h/.cpp pair of files, and each
platform-specific module lives in its own separate pair of files
(for simple classes, the .cpp files often aren't needed, however).
The user #includes the generic header and the platform-specific
header of his choosing. The last question is how to get the name
of the combined class down to a nice, short name.
In the example I gave for timer, I proposed a typedef at the end of
the platform-specific file, such as:
typedef basic_timer<c_timer_impl> timer; // For the "default" timer.
Other platform-specific files would have similiar typedefs:
typedef basic_timer<performance_counter_impl> pc_timer;
However, after reconsidering this, I don't think it is such a good idea,
since it adds a bunch of xx_timer variations into the boost namespace.
I think what would be better is to not supply a typedef at all,
and let the user supply one at whatever scope is appropriate.
For example, if the user intended to use one kind of timer throughout
his entire program, he could place a global typedef like this:
typedef basic_timer<c_timer_impl> timer;
in a common include file. The advantage here is that if down the road,
he found a better implementation, he could change one line of code to:
typedef basic_timer<cool_new_timer_impl> timer;
and leave the rest of the program untouched, and it would recompile to
use the new timer.
The nice thing about making the user do the typedef, is that it doesn't
have to be global in scope. If a user needs different timers in different
places, he can scope a different typedef in each class/function/block that
uses a timer. The code can still just refer to the name timer, so
that changing implementations is still as easy as possible; it just has
more granularity than a global implementation.
The technique of using a templatized implementation class is useful in
general, not just with timers. However, the ability to use a
user-defined typedef is limited to classes that aren't naturally
templates themselves. For example, suppose that std::vector were
std::basic_vector, and so the user could try to typedef his own vector
with his own allocator. He's want to do something like:
template<class T, class P>
typedef std::basic_vector<T,P,my_allocator_impl> vector;
Since C++ doesn't allow templatizing typedefs ( :-( ), this wouldn't
work. There are workarounds for this, but we can defer worrying about
them until boost comes up a with a templatized class that needs
platform-specific specialization.
------------------------------------------------------------------------
eGroups.com home: http://www.egroups.com/group/boost
http://www.egroups.com - Simplifying group communications
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk