On 1/23/07, Joaquín Mª López Muñoz wrote:
it might be a good idea to provide an additional
predefined
key extractor for use with free functions so as to supplement the existing
ones working with member functions, I'll add this to my to consider list.
Hope this helps,
Joaquín M López Muñoz
Telefónica, Investigación y Desarrollo
I'm currently experimenting with a rule of thumb where my extensible
template classes are all written using policies, but the default for each
policy is one that calls a free function. Sort of a best of both worlds
approach - or at least that's what I'm hoping. For example, intrusive_ptr
could be rewritten to take an AddRef policy, and the default could be to
call intrusive_ptr_add_ref, etc:
template <typename T>
struct intrusive_ptr_default_add_ref_policy
{
static void add_ref(T * t)
{
intrusive_ptr_add_ref(t);
}
};
template
struct intrusive_ptr
{
intrusive_ptr(...)
{
...
AddRefPolicy::add_ref(t);
}
};
So user can implement intrusive_ptr_add_ref() OR implement a policy class.
Might not be worthwhile for intrusive_ptr but it's an easy example.
Probably makes more sense for templates where you might actually want
different behaviours for a particular type, in different contexts. Much
like passing in a predicate to std::map<>, yet the default is std::less,
which is based on the type's intrinsic operator<().
Speaking of map<> and std::less(), I kind of wish they added one extra point
of abstraction there - something like std::order() or map_order() or
key_order(), that was allowed to be overridden. The idea being that some
types can have a meaningful order() when used as a key, that is different
than the meaningful operator<(). In my case it was a string class
consisting of shared static strings - so that, used as a key, they could be
quickly compared using the actual pointer to the shared memory, so
operator<() would be implemented using that method; but used as a typical
string, you might want to order them aphabetically, so operator<() should be
a lexigraphical compare. And yes, I could just make sure my map<> took a
custom predicate, but I'd rather the string class control that 'intrinsic',
and not have to police future uses of the class when used as a key, to
ensure the right predicate is used.
The real answer probably is that std::map<> should call a free function,
like, say, extract_key(T const & t), and then call the predicate on that,
instead of on T.
Hey, which gets us right back to where we started - multi-index DOES have
key-extraction (making it better than std::map<> already), and the OP is
asking for it to be a free function! Now if we could only get std::map<> to
use it...
Tony